[几何] BZOJ 4814 [Cqoi2017]小Q的草稿
2017-04-21 08:14
323 查看
把三角形拆成三条线段
以每个点为中心 极角排序一发 然后扫描线 set中维护线段 优先级为到中心点的距离 因为三角形不相交 所以大小关系不会变
遇到一个点就查一下最近的线段是不是挡住了 不然就有贡献
其实三角形对于一个点 只有一条边是有用的
以每个点为中心 极角排序一发 然后扫描线 set中维护线段 优先级为到中心点的距离 因为三角形不相交 所以大小关系不会变
遇到一个点就查一下最近的线段是不是挡住了 不然就有贡献
其实三角形对于一个点 只有一条边是有用的
#include<cstdio> #include<cstdlib> #include<algorithm> #include<cmath> #include<set> using namespace std; typedef double ld; inline char nc(){ static char buf[100000],*p1=buf,*p2=buf; return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++; } inline void read(int &x){ char c=nc(),b=1; for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1; for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b; } const int N=5005; const ld PI=acos(-1.0); const ld eps=1e-8; inline int sgn(ld a){ if (fabs(a)<eps) return 0; return a<0?-1:1; } struct PP{ ld x,y,ang; PP(ld x=0,ld y=0):x(x),y(y) { } ld dis(){ return sqrt(x*x+y*y); } void get() { ang=atan2(y,x); } void read(){ int _x,_y; ::read(_x); ::read(_y); x=_x; y=_y; } friend PP operator + (PP A,PP B){ return PP(A.x+B.x,A.y+B.y); } friend PP operator - (PP A,PP B){ return PP(A.x-B.x,A.y-B.y); } friend ld operator * (PP A,PP B){ return A.x*B.y-A.y*B.x; } friend PP operator * (PP A,ld B) { return PP(A.x*B,A.y*B); } friend ld dot(PP A,PP B){ return A.x*B.x+A.y*B.y; } bool operator < (const PP &B) const{ return ang<B.ang; } friend PP I(PP a1,PP a2,PP b1,PP b2){ ld t=((b2-b1)*(a1-b1))/((a2-a1)*(b2-b1)); return a1+(a2-a1)*t; } }; PP tag; struct SS{ PP u,v; SS() {} SS(PP u,PP v):u(u),v(v) { } bool operator < (const SS& B) const{ return I(u,v,PP(0,0),tag).dis()<I(B.u,B.v,PP(0,0),tag).dis(); } }S ; multiset<SS> Set; multiset<SS>::iterator it ; struct event{ int f,idx; ld ang; event() {} event(int f,int idx,ld ang):f(f),idx(idx),ang(ang) { } bool operator < (const event &B) const{ return sgn(ang-B.ang)==0?f>B.f:sgn(ang-B.ang)<0; } }ev ; int tot; int n,m,ans; PP _p ,p ,_t [3],t [3]; int pt,sg; inline void Solve(){ tot=0; for (int i=1;i<=sg;i++) ev[++tot]=event(1,i,S[i].u.ang),ev[++tot]=event(0,i,S[i].v.ang); sort(p+1,p+pt+1); sort(ev+1,ev+tot+1); Set.clear(); int ret=0; int j=1; for (int i=1;i<=pt;i++){ while (j<=tot && (sgn(ev[j].ang-p[i].ang)<0 || (sgn(ev[j].ang-p[i].ang)==0 && ev[j].f))){ if (ev[j].f) tag=S[ev[j].idx].u,it[ev[j].idx]=Set.insert(S[ev[j].idx]); else tag=S[ev[j].idx].v,Set.erase(it[ev[j].idx]); j++; } if (Set.empty()){ ++ret; continue; } tag=p[i]; ld dis=I((*Set.begin()).u,(*Set.begin()).v,0,tag).dis(); if (sgn(p[i].dis()-dis)<=0) ret++; } ans+=ret; } int main(){ freopen("t.in","r",stdin); freopen("t.out","w",stdout); read(n); read(m); for (int i=1;i<=n;i++) _p[i].read(); for (int i=1;i<=m;i++) for (int j=0;j<3;j++) _t[i][j].read(); for (int i=1;i<=n;i++){ pt=sg=0; for (int j=i+1;j<=n;j++) (p[++pt]=_p[j]-_p[i]).get(); for (int j=1;j<=m;j++){ for (int k=0;k<3;k++) t[j][k]=_t[j][k]-_p[i]; ld maxv=0; PP u,v; for (int k=0;k<3;k++){ ld ang=dot(t[j][k],t[j][(k+1)%3])/t[j][k].dis()/t[j][(k+1)%3].dis(); ang=acos(ang); if (ang>maxv) maxv=ang,u=t[j][k],v=t[j][(k+1)%3]; } u.get(); v.get(); if (u.ang>v.ang) swap(u,v); if (v.ang-u.ang<PI) S[++sg]=SS(u,v); else{ PP tmp=I(u,v,PP(0,0),PP(-1.0,0)); S[++sg]=SS(tmp,u),S[sg].u.ang=-PI,S[++sg]=SS(v,tmp),S[sg].v.ang=PI; } } Solve(); } printf("%d\n",ans); return 0; }
相关文章推荐
- bzoj 4814: [Cqoi2017]小Q的草稿【计算几何】
- bzoj 4814 [Cqoi2017]小Q的草稿
- 4814: [Cqoi2017]小Q的草稿
- [分块 莫比乌斯反演] BZOJ 4815 [Cqoi2017]小Q的表格
- bzoj4814: [Cqoi2017]小Q的草稿
- bzoj4815 [Cqoi2017]小Q的表格
- bzoj 4815: [Cqoi2017]小Q的表格
- bzoj 4813: [Cqoi2017]小Q的棋盘 树形dp
- 【bzoj4813】[Cqoi2017]小Q的棋盘 树上dfs+贪心
- bzoj 4815: [Cqoi2017]小Q的表格【欧拉函数+分块】
- BZOJ_4813_[Cqoi2017]小Q的棋盘_dfs
- bzoj4815 [Cqoi2017]小Q的表格
- [bzoj4813][Cqoi2017]小Q的棋盘
- bzoj 4813: [Cqoi2017]小Q的棋盘【树形dp】
- bzoj 4815: [Cqoi2017]小Q的表格 [数论]
- BZOJ4813 [Cqoi2017]小Q的棋盘
- 【BZOJ】 4813: [Cqoi2017]小Q的棋盘
- bzoj 4813: [Cqoi2017]小Q的棋盘
- bzoj 4815: [Cqoi2017]小Q的表格 分块+莫比乌斯反演
- BZOJ 4813: [Cqoi2017]小Q的棋盘 (树形dp)