Problem K. Kingdom Division 2

来源:互联网 发布:爱知大学怎么样 编辑:程序博客网 时间:2024/06/11 17:11
Problem K. Kingdom Division 2
Input le: kingdom.in
Output le: kingdom.out
Time limit: 2 seconds
Memory limit: 256 megabytes
Once upon a time there was a kingdom ruled by a wise king. After forty years of his reign, by means of
successful military actions and skillful diplomacy, the kingdom became a convex polygon with n vertices.
This form of the kingdom greatly simplied tax collection and land division between the inhabitants, so
everybody was happy.
But nothing lasts forever, and one autumn evening the king suddenly died. Due to the laws of the kingdom,
the oldest son of the king should have taken the kingdom, but the problem was that he had two twin
sons. It was widely known that the king loved his sons equally, so it was not even pronounced to choose
only one son to rule.
After ten days of serious thoughts it was nally decided to split the kingdom into two parts  one per
each son. Remembering the sad story of another kingdom that tried to divide the kingdom into two parts
of equal area, wise men of the kingdom in this problem decided to use another way of kingdom division.
There are two cities in the kingdom, Andrewville and Bettyburg. It was decided to divide the kingdom
by a straight line in such way that:
• The line connects two vertices of the polygon.
• Andrewville and Bettyburg are strictly inside of the parts that the polygon is divided to, and belong
to dierent parts.
However it turned out that there are several ways to do the division. People of the kingdom don't know
how to choose the optimal way to do it, so they rst decided to count the number of ways. Help them to
do it.
Input
The input le contains several test cases. Each test case starts with n  the number of vertices of the
polygon (4 ≤ n ≤ 100 000). The following n lines contain vertices of the polygon in counterclockwise
order. No three vertices are on the same line.
Two lines follow, containing coordinates of Andrewville and Bettyburg, respectively. The cities are at
dierent points strictly inside the given polygon.
Coordinates of all points do not exceed 109 by their absolute values.
The last test case is followed by n = 0, it must not be processed.
The sum of n for all test cases in the input le is at most 100 000.
Output

For each test case output one integer  the number of ways to divide the kingdom.

Example: 

Input:5
0 0
6 0
6 4
3 6
0 4
4 1
1 4
4
0 0
4 0
4 4
0 4
1 1
3 1
0

Output:

3

0

:

题目大概意思是有一个n点的凸包,内部有两个点a、b,要求连接任意两个顶点,使得:1.凸包被分成两部分;2.两个点a、b在不同的子块里

划一下图大概就能看出来,对于某一个顶点x来说,能和它完成匹配的点在射线xa和xb的夹缝中间,所以这是一个查找问题,通过比较斜率,

然后找出来夹缝中距离x点l1和l2长度的两个最接近射线边界的点,则其中符合条件的点的个数是l1和l2的差,最后所有的和相加除以2就可以了,

因为n的基数比较大,所以用二分查找

/*PROBLEM K : "SOLVED" *//*TIME : ______________*/#include "cstdio"#include "cstring"#include "cctype"#include "algorithm"#include "cmath"#include "vector"using namespace std;#define Inc(i, a, b) for(int i = a; i < b; i++)#define Dec(i, a, b) for(int i = a; i > b; i--)#define Mem(a, x) memset(a, x, sizeof(a))#define Pii pair<int, int> #define Pdd pair<double, double>#define Cin scanf#define Put printf#define CIN(a) scanf("%d", &a)#define CII(a, b) scanf("%d%d", &a, &b)#define CIS(a) scanf("%s", a)#define PUT(a) printf("%d\n", a) #define PII(a, b) printf("%d %d\n", a, b)#define PUS(a) printf("%s\n", a)#define Pub push_back#define Mpi make_pair#define lson l, mid, rt<<1#define rson mid+1, r, rt<<1|1#define ll long long#define maxn 100005#define pi acos(-1)#define eps 1e-10struct Point {int x, y;Point() {}Point(int x, int y) : x(x), y(y) {}} ;Point point[maxn];Point a, b;int n;//void solvell xmul(Point p0, Point p1, Point p2) {return (ll)(p1.x - p0.x) * (p2.y - p0.y) - (ll)(p2.x - p0.x) * (p1.y - p0.y);}ll cala(int t) {int l = 1, r = n - 1;while(l < r) {int mid = (l + r) >> 1;if(xmul(point[t], point[(t + mid) % n], a) < 0 || xmul(point[t], point[(t + mid) % n], b) < 0)r = mid;else l = mid + 1;}ll l1 = xmul(point[t], point[(t + l) % n], a);ll l2 = xmul(point[t], point[(t + l) % n], b);if((l1 < 0 && l2 < 0) || (l1 >= 0 && l2 >= 0)) return -1;return l;}ll calb(int t) {int l = 1, r = n - 1;while(l < r) {int mid = (l + r) >> 1;if(xmul(point[t], point[(t + mid) % n], a) > 0 || xmul(point[t], point[(t + mid) % n], b) > 0)l = mid + 1;else r = mid;}return l;}void Solve() {ll ans = 0;Inc(i, 0, n) {ll t1 = cala(i);if(t1 < 0) continue;ll t2 = calb(i);ans += t2 - t1;}Put("%lld\n", ans / 2);}int main() {freopen("kingdom.in", "r", stdin);freopen("kingdom.out", "w", stdout);while(CIN(n), n) {Inc(i, 0, n) CII(point[i].x, point[i].y);CII(a.x, a.y); CII(b.x, b.y);Solve();}}


0 0