You are a fan of Josh and you bought this glass at the astronomical sum of money. Since the glass is thick enough to put erectly on the table, you want to know in total how many ways you can put it so that you can enjoy as many as possible different paintings hiding on the glass. We assume that material of the glass is uniformly distributed. If you can put it erectly and stably in any ways on the table, you can enjoy it.
More specifically, if the polygonal glass is like the polygon in Figure 1, you have just two ways to put it on the table, since all the other ways are not stable. However, the glass like the polygon in Figure 2 has three ways to be appreciated.
Pay attention to the cases in Figure 3. We consider that those glasses are not stable.
For each test case, the first line is an integer n representing the number of lines of the polygon. (3<=n<=50000). Then n lines follow. The ith line contains two real number xi and yi representing a point of the polygon. (xi, yi) to (xi+1, yi+1) represents a edge of the polygon (1<=i<n), and (xn,yn) to (x1, y1) also represents a edge of the polygon. The input data insures that the polygon is not self-crossed.
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
using namespace std;
typedef long long LL; const int MAXN = ;
const double EPS = 1e-; inline int sgn(double x) {
return (x > EPS) - (x < -EPS);
} struct Point {
double x, y;
Point(double x = , double y = ): x(x), y(y) {}
void read() {
scanf("%lf%lf", &x, &y);
}
Point operator + (const Point &rhs) const {
return Point(x + rhs.x, y + rhs.y);
}
Point operator - (const Point &rhs) const {
return Point(x - rhs.x, y - rhs.y);
}
double operator * (const Point &rhs) const {
return x * rhs.x + y * rhs.y;
}
Point operator / (const double &rhs) const {
return Point(x / rhs, y / rhs);
}
bool operator < (const Point &rhs) const {
if(y != rhs.y) return y < rhs.y;
return x < rhs.x;
}
};
typedef Point Vector; double cross(const Point &a, const Point &b) {
return a.x * b.y - a.y * b.x;
} double cross(const Point &sp, const Point &op, const Point &ep) {
return cross(sp - op, ep - op);
} void Graham_scan(Point *p, int n, int *stk, int &top) {
sort(p, p + n);
top = ;
stk[] = ; stk[] = ;
for(int i = ; i < n; ++i) {
while(top && cross(p[stk[top - ]], p[stk[top]], p[i]) <= ) --top;
stk[++top] = i;
}
int len = top;
stk[++top] = n - ;
for(int i = n - ; i >= ; --i) {
while(top != len && cross(p[stk[top - ]], p[stk[top]], p[i]) <= ) --top;
stk[++top] = i;
}
} Point barycenter(Point *p, int n) {
double area = ;
Point res;
for(int i = ; i < n; ++i) {
double t = cross(p[i], p[i + ]) / ;
res.x += t * (p[i].x + p[i + ].x) / ;
res.y += t * (p[i].y + p[i + ].y) / ;
area += t;
}
return res / area;
} Point p[MAXN];
int stk[MAXN], top;
int n, T; int main() {
scanf("%d", &T);
while(T--) {
scanf("%d", &n);
for(int i = ; i < n; ++i) p[i].read();
p[n] = p[];
Point O = barycenter(p, n);
Graham_scan(p, n, stk, top); int ans = ;
for(int i = ; i < top; ++i) {
Point &A = p[stk[i]], &B = p[stk[i + ]];
ans += (sgn((O - A) * (B - A)) > && sgn((O - B) * (A - B)) > );
}
printf("%d\n", ans);
}
}