真●半平面交,半平面交模板题,按照题目描述将每个多边形拆分成n个向量,我们规定向量的左侧为其指定的区域,参照了Po姐的写法,因为双端队列实在是不好搞,我们先在一个方向加线,然后再在最后删队首队尾,值得注意的是用向量求交点和用向量判断一个点是否在这条向量的左面。
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<iostream>
#include<iomanip>
#include<ctime>
#include<cmath>
#include<algorithm>
using namespace std;
struct point
{
double x,y;
point(){}
point(double _,double __):x(_),y(__){}
point operator + (point b)
{
return point(x+b.x,y+b.y);
}
point operator - (point b)
{
return point(x-b.x,y-b.y);
}
double operator * (point b)
{
return x*b.y-y*b.x;
}
point operator * (double rate)
{
return point(x*rate,y*rate);
}
}pp[1000];
struct line
{
point p,v;
double alpha;
bool operator < (line b) const
{
return alpha<b.alpha;
}
line(){}
line(point a,point b):p(a),v(b-a)
{
alpha=atan2(v.y,v.x);
}
point operator ^ (line b)
{
point mid=p-b.p;
double rate=(b.v*mid)/(v*b.v);
return p+v*rate;
}
}lines[1000000];
int tot;
bool onleft(point p,line l)
{
point mid=p-l.p;
return l.v*mid>=0;
}
line dui[1000000];
int top=1,my_final=1;
void get_half_plane_intersection()
{
sort(lines+1,lines+1+tot);
for(int i=1;i<=tot;i++)
{
while(my_final-top>=2 && !onleft(dui[my_final-1]^dui[my_final-2],lines[i])) my_final--;
if(my_final-top>=1 && fabs(dui[my_final-1].v*lines[i].v)<=0)
dui[my_final-1]=onleft(lines[i].p,dui[my_final-1])?lines[i]:dui[my_final-1];
else dui[my_final++]=lines[i];
}
while(1)
{
if(my_final-top>=2 && !onleft(dui[my_final-1]^dui[my_final-2],dui[top])) my_final--;
else if(my_final-top>=2 && !onleft(dui[top]^dui[top+1],dui[my_final-1])) top++;
else break;
}
}
int main()
{
int n,m;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&m);
for(int i=1;i<=m;i++)
{
scanf("%lf%lf",&pp[i].x,&pp[i].y);
if(i!=1) lines[++tot]=line(pp[i-1],pp[i]);
}
lines[++tot]=line(pp[m],pp[1]);
}
get_half_plane_intersection();
if(my_final-top<=2) printf("0.000\n");
else
{
int sum=0;
for(int i=top+1;i<my_final;i++) pp[++sum]=dui[i-1]^dui[i];
pp[++sum]=dui[my_final-1]^dui[top];
double ans=0;
for(int i=2;i<=sum;i++) ans+=pp[i-1]*pp[i];
ans+=pp[sum]*pp[1];
printf("%.3lf\n",ans/2);
}
return 0;
}