题意:给一个凸多边形,求以凸多边形的顶点为顶点的三角形中,有多少个面积小于给定数值K?
思路:旋转卡壳+二分答案
时间复杂度:n^2logn
1 #include<iostream>
2 #include<cstdio>
3 #include<cmath>
4 #include<cstring>
5 using namespace std;
6 #define MAXN 1001
7 struct point
8 {
9 long long x,y;
10 point() {}
11 point(long long x0,long long(y0)): x(x0),y(y0) {}
12 };
13 int n,T;
14 long long max_area;
15 point a[2*MAXN];
16 int edge[MAXN][MAXN][2];
17 point operator -(const point &A,const point &B)
18 {
19 return point(A.x-B.x,A.y-B.y);
20 }
21 long long cross(point A,point B)
22 {
23 return A.x*B.y-A.y*B.x;
24 }
25 void rotate()
26 {
27 int i,k;
28 int j1,j2;
29 for(k=1;k<n;k++)
30 {
31 j1=1; j2=k+1;
32 for(i=1;i<=n;i++)
33 {
34 if(i+k>n) break;
35 while(abs(cross(a[i]-a[j1+1],a[i+k]-a[j1+1]))>abs(cross(a[i]-a[j1],a[i+k]-a[j1])))
36 j1=j1%n+1;
37 edge[i][i+k][0]=j1;
38 while(abs(cross(a[i]-a[j2+1],a[i+k]-a[j2+1]))>abs(cross(a[i]-a[j2],a[i+k]-a[j2])))
39 j2=j2%n+1;
40 edge[i][i+k][1]=j2;
41 }
42 }
43 }
44 int binary(int i,int k,int j)
45 {
46 long long s;
47 int left=i,right;
48 int ans=0;
49 if(k<i) right=k+n;
50 else right=k;
51 while(left<right)
52 {
53 int mid=(left+right)/2;
54 s=abs(cross(a[i]-a[mid],a[j]-a[mid]));
55 if(max_area<s) right=mid;
56 else left=mid;
57 if(right-left==1) break;
58 }
59 ans=left-i;
60
61 left=k;
62 if(j<k) right=j+n;
63 else right=j;
64 while(left<right)
65 {
66 int mid=(left+right)/2;
67 s=abs(cross(a[i]-a[mid],a[j]-a[mid]));
68 if(max_area<s) left=mid;
69 else right=mid;
70 if(right-left==1) break;
71 }
72 ans+=(j+n-right)%n;
73 return ans;
74 }
75 int solve()
76 {
77 int i,j;
78 long long ans=0;
79 int k1,k2;
80 long long s;
81 for(i=1;i<n;i++)
82 for(j=i+1;j<=n;j++)
83 {
84
85 k1=edge[i][j][0]; k2=edge[i][j][1];
86 s=abs(cross(a[i]-a[k1],a[j]-a[k1]));
87 if(j>i+1)
88 {
89 if(max_area>=s) ans+=j-i-1;
90 else
91 ans+=binary(i,k1,j);
92 }
93 if(i+n>j+1)
94 {
95 s=abs(cross(a[i]-a[k2],a[j]-a[k2]));
96 if(max_area>=s) ans+=i+n-j-1;
97 else
98 ans+=binary(j,k2,i);
99 }
100 }
101 return ans/3;
102 }
103 int main()
104 {
105 scanf("%d",&T);
106 int i,j;
107 for(j=1;j<=T;j++)
108 {
109 scanf("%d%lld",&n,&max_area);
110 max_area*=2;
111 for(i=1;i<=n;i++)
112 {
113 scanf("%lld%lld",&a[i].x,&a[i].y);
114 a[n+i]=a[i];
115 }
116 rotate();
117 printf("%d\n",solve());
118 }
119 return 0;
120 }