[NOI.AC省选模拟赛3.31] 星辰大海 [半平面交]

题面

传送门

思路

懒得解释了......也是比较简单的结论

但是自己看到几何就退缩了......

下周之内写一个计算几何的学习笔记!

[NOI.AC省选模拟赛3.31] 星辰大海 [半平面交]

Code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cassert>
#include<cmath>
#define eps 1e-14
using namespace std;
inline int read(){
int re=0,flag=1;char ch=getchar();
while(!isdigit(ch)){
if(ch=='-') flag=-1;
ch=getchar();
}
while(isdigit(ch)) re=(re<<1)+(re<<3)+ch-'0',ch=getchar();
return re*flag;
}
/*
Calculating the intersection of two segments:
method 1: Brute force implemention -> get 4 equations, take the position of target point as the unknown factor
method 2: Solve using vector -> the 'x-multiple' of two planary vectors is the SIGNED area of the paralellogram formed by them.
ALWAYS MIND the sign before the area (refer to function cross(seg,seg) for further detail)
*/
int T,N,n,m;
inline int sign(const long double &d){
if(d>eps) return 1;
if(d<-eps) return -1;
return 0;
}
struct p{
long double x,y;
p(long double xx=0.0,long double yy=0.0){x=xx;y=yy;}
}rt[1000010];
inline p operator *(const p &a,const long double &b){return p(a.x*b,a.y*b);}
inline long double operator *(const p &a,const p &b){return a.x*b.y-a.y*b.x;}//'x-multiple' of planary vector
inline p operator -(const p &a,const p &b){return p(a.x-b.x,a.y-b.y);}
inline p operator +(const p &a,const p &b){return p(a.x+b.x,a.y+b.y);}
struct ele{
p a;long double k;
}lis[1000010];
struct seg{
p a,b;long double k;
seg(p aa=p(),p bb=p(),long double kk=0.0){a=aa;b=bb;k=kk;}
}a[1000010],q[1000010];
inline long double getk(const p &a){return atan2l(a.y,a.x);}//get the k-value of a pair<long double,dobule>
inline bool cmp(const ele &l,const ele &r){return l.k<r.k;}
inline bool operator <(const seg &l,const seg &r){return l.k<r.k;}//sort according to k
inline p cross(const seg &x,const seg &y){//calculate the intersection using planary vector
long double v1=(x.a-y.b)*(x.b-y.b);
long double v2=(x.a-y.a)*(x.b-y.a);
long double c=v1/(v1-v2);
p re=(y.b+((y.a-y.b)*c));
return re;
}
inline bool right(const p &x,const seg &y){//determine if x is to the right of y
return ((x-y.a)*(x-y.b))>=0;
}
inline long double solve(){
int i,head=1,tail=0,flag;long double re=0;
sort(a+1,a+m+1);
for(i=1;i<=m;i++){
flag=0;
while(head<=tail&&(!sign(a[i].k-q[tail].k))){//get rid of segments at same k
if((q[tail].a-a[i].a)*(q[tail].a-a[i].b)>=0) tail--;//if old one is to the right of current one, delete it
else{flag=1;break;}//or else, the current one shall be deleted
}
if(flag) continue;
while(head<tail&&right(rt[tail],a[i])) tail--;//check if the intersection is to the right, if so delete the foremost/backmost segment
while(head<tail&&right(rt[head+1],a[i])) head++;
q[++tail]=a[i];
if(head<tail) rt[tail]=cross(q[tail-1],q[tail]);
}
while(head<tail&&right(rt[tail],q[head])) tail--;
while(head<tail&&right(rt[head+1],q[tail])) head++;
rt[head]=rt[tail+1]=cross(q[head],q[tail]);//mind that the first and last points are adjacent
for(i=head;i<=tail;i++){
re+=rt[i]*rt[i+1];
}
return re;
}
const long double pi=acosl(-1.0);
const p ur(1e6,1e6);
const p ul(-1e6,1e6);
const p dr(1e6,-1e6);
const p dl(-1e6,-1e6);
const seg rr(ur,dr,-pi*0.5);
const seg dd(dr,dl,pi);
const seg ll(dl,ul,pi*0.5);
const seg uu(ul,ur,0);
int main(){
N=read();T=read();int flag,i,j;
while(T--){
n=read();
m=0;
a[++m]=rr;a[++m]=dd;a[++m]=ll;a[++m]=uu;
for(i=1;i<=n;i++){
lis[i].a.x=read();
lis[i].a.y=read();
}
for(i=2;i<=n;i++){
lis[i].k=getk(lis[i].a-lis[1].a);
}
sort(lis+2,lis+n+1,cmp);
for(i=2;i<=n;i++){
lis[i+n-1]=lis[i];
lis[i+n-1].k+=2.0*pi;
}
flag=1;j=2;
for(i=2;i<=n;i++){
j=max(i,j);
while(lis[j+1].k-lis[i].k<pi+eps) j++;
if((!sign(lis[i+1].k-lis[i].k))||(!sign(lis[i].k+pi-lis[j].k))){
flag=0;puts("0");break;
}
if(j!=i) a[++m]=seg(lis[j].a,lis[i].a,getk(lis[i].a-lis[j].a));
if(lis[i+1].k-lis[i].k<pi+eps) a[++m]=seg(lis[i+1].a,lis[i].a,getk(lis[i].a-lis[i+1].a));
}
if(flag) printf("%.9lf\n",(double)solve()*0.5);
}
}
上一篇:圆形图片CustomShapeImageView


下一篇:使用纯粹的JS构建 Web Component