【半平面交模板】bzoj2618 [Cqoi2006]凸多边形
理解好求两直线交点的公式
单调队列最后用 队尾弹队首 队首弹队尾
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<algorithm>
using namespace std;
const int N=500+5; const double eps=1e-8;
int dcmp(double x)
{if(fabs(x)<=eps) return 0;
if(x>0) return 1;
return -1;
}
int n,head,tail,m,cnt; double ans;
struct point
{double x,y;
point operator + (point r) const{point t; t.x=x+r.x; t.y=y+r.y; return t;}
point operator - (point r) const{point t; t.x=x-r.x; t.y=y-r.y; return t;}
double operator * (point r) const{return x*r.y-y*r.x;}
point operator * (double r)const{point t; t.x=x*r; t.y=y*r; return t;}
}b[N];
struct line
{point p1,p2; double th;
bool operator <(line b) const
{if(dcmp(th-b.th)==0) return dcmp((p2-p1)*(b.p2-p1))<0;
return dcmp(th-b.th)<0;
}
}a[N],q[N];
inline point get(line a,line b)
{point va=a.p2-a.p1,
vb=b.p2-b.p1,
u=b.p1-a.p1;
point re=b.p1+vb*((u*va)/(va*vb));
return re;
}
inline bool judge(line a,line b,line k)
{point p=get(a,b);
return dcmp((k.p2-k.p1)*(p-k.p1))<0;
}
inline void half()
{sort(a+1,a+m+1);
for(int i=1;i<=m;i++) if(dcmp(a[i].th-a[i-1].th)!=0) a[++cnt]=a[i];
head=1; tail=0;
q[++tail]=a[1]; q[++tail]=a[2];
for(int i=3;i<=cnt;i++)
{while(head<tail && judge(q[tail-1],q[tail],a[i])) tail--;
while(head<tail && judge(q[head+1],q[head],a[i])) head++;
q[++tail]=a[i];
}
while(head<tail && judge(q[tail-1],q[tail],q[head])) tail--;
while(head<tail && judge(q[head+1],q[head],q[tail])) head++;
q[tail+1]=q[head];
for(int i=head;i<=tail;i++) b[++n]=get(q[i],q[i+1]);
}
int main()
{
int num,k; scanf("%d",&k);
while(k--)
{scanf("%d",&num);
for(int i=1;i<=num;i++) scanf("%lf%lf",&b[i].x,&b[i].y);
b[num+1]=b[1];
for(int i=1;i<=num;i++) a[++m].p1=b[i],a[m].p2=b[i+1];
}
for(int i=1;i<=m;i++) a[i].th=atan2(a[i].p2.y-a[i].p1.y,a[i].p2.x-a[i].p1.x);
half();
b[n+1]=b[1];
for(int i=1;i<=n;i++) ans+=b[i]*b[i+1];
ans=fabs(ans)/2.0;
printf("%.3lf",ans);
return 0;
}