[模板] 半平面交
做法
考虑用射线(一个点和一个向量)表示它左侧的半平面
那么我们可以先按与x轴正半轴夹角(可用atan2(y,x)实现)排序,然后再用双端队列维护当前在交中的射线即可
之所以要用双端队列,是因为新插入一个半平面时队首和队尾都有可能被弹出,而且要注意的是,要先弹队尾再弹队首
在最后,还要再用队首的弹一些队尾的
例题
luogu4196 凸多边形
1 #include<bits/stdc++.h> 2 #define pa pair<int,int> 3 #define CLR(a,x) memset(a,x,sizeof(a)) 4 #define MP make_pair 5 #define fi first 6 #define se second 7 using namespace std; 8 typedef long long ll; 9 typedef unsigned long long ull; 10 typedef unsigned int ui; 11 typedef long double ld; 12 const int maxl=2333,maxn=12,maxm=55; 13 const ld eps=1e-9; 14 15 inline char gc(){ 16 return getchar(); 17 static const int maxs=1<<16;static char buf[maxs],*p1=buf,*p2=buf; 18 return p1==p2&&(p2=(p1=buf)+fread(buf,1,maxs,stdin),p1==p2)?EOF:*p1++; 19 } 20 inline ll rd(){ 21 ll x=0;char c=gc();bool neg=0; 22 while(c<'0'||c>'9'){if(c=='-') neg=1;c=gc();} 23 while(c>='0'&&c<='9') x=(x<<1)+(x<<3)+c-'0',c=gc(); 24 return neg?(~x+1):x; 25 } 26 27 struct Node{ 28 ld x,y; 29 Node(ld _x=0,ld _y=0){x=_x,y=_y;} 30 }p[maxn][maxm],it[maxl]; 31 struct Line{ 32 Node x,y; 33 Line(Node _x=0,Node _y=0){x=_x,y=_y;} 34 }l[maxl]; 35 int N,M[maxn],cnt; 36 int hd,tl,q[maxl]; 37 38 inline ld operator ^(const Node a,const Node b){return a.x*b.y-a.y*b.x;} 39 inline Node operator +(const Node a,const Node b){return Node(a.x+b.x,a.y+b.y);} 40 inline Node operator -(const Node a,const Node b){return Node(a.x-b.x,a.y-b.y);} 41 inline Node operator *(const Node a,const ld b){return Node(a.x*b,a.y*b);} 42 inline ld myabs(const ld x){return x>0?x:-x;} 43 inline Node inter(const Line a,const Line b){ 44 ld k1=(a.y-a.x)^(b.y-a.x),k2=(b.x-a.x)^(a.y-a.x); 45 return b.x+(b.y-b.x)*(k2/(k1+k2)); 46 } 47 inline bool onright(const Line a,const Node b){return ((b-a.x)^(a.y-a.x))>=-eps;} 48 inline ld slope(Line a){return atan2((a.y-a.x).y,(a.y-a.x).x);} 49 50 inline bool cmp(Line a,Line b){ 51 ld x=slope(a),y=slope(b); 52 return (myabs(x-y)<eps)?(!onright(b,a.x)):(x<y); 53 } 54 55 inline ld solve(){ 56 sort(l+1,l+cnt+1,cmp); 57 hd=1,tl=0; 58 for(int i=1;i<=cnt;i++){ 59 // printf("~%Lf %Lf\n",(l[i].y-l[i].x).x,(l[i].y-l[i].x).y); 60 if(i>1&&myabs(slope(l[i])-slope(l[i-1]))<eps) continue; 61 while(hd<tl&&onright(l[i],inter(l[q[tl]],l[q[tl-1]]))) tl--; 62 while(hd<tl&&onright(l[i],inter(l[q[hd]],l[q[hd+1]]))) hd++; 63 q[++tl]=i; 64 } 65 while(hd<tl&&onright(l[q[hd]],inter(l[q[tl]],l[q[tl-1]]))) tl--; 66 // while(hd<tl&&onright(l[q[tl]],inter(l[q[hd]],l[q[hd+1]]))) hd++; 67 // for(int i=hd;i<=tl;i++) printf("~%Lf %Lf %Lf %Lf\n",l[q[i]].x.x,l[q[i]].x.y,l[q[i]].y.x,l[q[i]].y.y); 68 if(hd+2>tl) return 0; 69 ld re=0; 70 q[tl+1]=q[hd];int n=0; 71 for(int i=hd;i<=tl;i++) it[++n]=inter(l[q[i]],l[q[i+1]]); 72 for(int i=2;i<n;i++) re+=myabs((it[i]-it[1])^(it[i+1]-it[1])); 73 return re/2; 74 } 75 76 int main(){ 77 //freopen("","r",stdin); 78 N=rd(); 79 for(int i=1;i<=N;i++){ 80 M[i]=rd(); 81 for(int j=0;j<M[i];j++) 82 p[i][j].x=rd(),p[i][j].y=rd(); 83 for(int j=0;j<M[i];j++){ 84 l[++cnt]=Line(p[i][j],p[i][(j+1)%M[i]]); 85 } 86 } 87 printf("%.3Lf\n",solve()); 88 return 0; 89 }