BZOJ3592 : Architext
首先特判多边形面积$=0$的情况,此时内部没有点,答案只会在顶点处取到。
对于面积$>0$的情况,离线询问,将所有多边形合在一起得到平面图,然后求出对偶图,那么每条多边形边的两侧分别对应对偶图中两个域。
每个多边形把这些域分成内外两个连通块,也就是保留除了多边形边之外的所有边后对偶图的连通情况。
把每个点随便放在所在的某个域之中,按时间分治,维护按秩合并的并查集。
对于每个询问任取一条多边形边,它两侧分别是域$A$和域$B$。那么有且仅有一个不与无穷域连通,假设是$A$,那么答案就是$A$所在连通块的信息。这会漏掉一些因为随便指派而不在连通块内的顶点。遍历每个顶点$x$,判断$x$所在域所在连通块是否和无穷域连通,是的话再把$x$的信息加入答案即可。
时间复杂度$O(n\log^2n)$。
#include<cstdio> #include<cmath> #include<set> #include<algorithm> #include<map> #include<vector> using namespace std; typedef pair<int,int>PI; typedef long long ll; const int N=50010,M=320010; int Case,n,m,cq,cnt,i,j,k,x,y,z,q[N],at[N]; map<PI,int>idx; int que[N][3]; vector<int>pool[N]; int dep[M],f[M],sum[M],mx[M],val[N]; int laste[M],lastv[N]; int co,op[N*3+M*2][3]; int MX,SUM; struct EV{ char op;int x,y,l,r; EV(){} EV(char _op,int _x,int _y,int _l,int _r){op=_op,x=_x,y=_y,l=_l,r=_r;} }; typedef vector<EV>V; struct P{ int x,y,d; ll operator*(const P&b){return 1LL*x*b.y-1LL*y*b.x;} }a[N]; struct E{ int x,y;double o; E(){} E(int _x,int _y){x=_x,y=_y,o=atan2(a[y].x-a[x].x,a[y].y-a[x].y);} }e[M]; bool del[M];int from[M]; namespace GetArea{ struct cmp{bool operator()(int a,int b){return e[a].o<e[b].o;}}; set<int,cmp>g[N];set<int,cmp>::iterator k;int i,j,q[M],t; void work(){ for(i=0;i<m+m;i++)if(!del[i]){ for(q[t=1]=j=i;;q[++t]=j=*k){ k=g[e[j].y].find(j^1);k++; if(k==g[e[j].y].end())k=g[e[j].y].begin(); if(*k==i)break; } ll s=0; for(j=1;j<=t;j++)s+=a[e[q[j]].x]*a[e[q[j]].y],del[q[j]]=1; if(s<=0)continue; for(cnt++,j=1;j<=t;j++){ from[q[j]]=cnt; at[e[q[j]].x]=at[e[q[j]].y]=cnt; } } } } inline void newedge(int x,int y){ if(idx.find(PI(x,y))!=idx.end())return; if(idx.find(PI(y,x))!=idx.end())return; e[m<<1]=E(x,y); e[m<<1|1]=E(y,x); idx[PI(x,y)]=idx[PI(y,x)]=m++; } inline int getid(int x,int y){return idx[PI(x,y)];} int F(int x){return f[x]==x?x:F(f[x]);} inline void merge(int x,int y){ x=F(x),y=F(y); if(x==y)return; if(dep[x]==dep[y]){ co++; op[co][0]='d'; op[co][1]=x; dep[x]++; } if(dep[x]<dep[y])swap(x,y); co++; op[co][0]='f'; op[co][1]=y; f[y]=x; if(mx[y]>mx[x]){ co++; op[co][0]='m'; op[co][1]=x; op[co][2]=mx[x]; mx[x]=mx[y]; } co++; op[co][0]='s'; op[co][1]=x; op[co][2]=sum[y]; sum[x]+=sum[y]; } inline void ins(int x,int y){ int z=F(at[x]); co++; op[co][0]='v'; op[co][1]=x; op[co][2]=val[x]; val[x]=y; if(y>mx[z]){ co++; op[co][0]='m'; op[co][1]=z; op[co][2]=mx[z]; mx[z]=y; } co++; op[co][0]='s'; op[co][1]=z; op[co][2]=y; sum[z]+=y; } inline void retrace(int t){ while(co>t){ if(op[co][0]=='d')dep[op[co][1]]--; else if(op[co][0]=='f')f[op[co][1]]=op[co][1]; else if(op[co][0]=='v')val[op[co][1]]=op[co][2]; else if(op[co][0]=='m')mx[op[co][1]]=op[co][2]; else sum[op[co][1]]-=op[co][2]; co--; } } inline void up(int&a,int b){a<b?(a=b):0;} void solve(int l,int r,V v){ int pos=co,mid=(l+r)>>1; V vl,vr; for(V::iterator it=v.begin();it!=v.end();it++){ if(it->l<=l&&r<=it->r){ if(it->op=='E')merge(it->x,it->y); else ins(it->x,it->y); }else{ if(it->l<=mid)vl.push_back(*it); if(it->r>mid)vr.push_back(*it); } } if(l==r){ if(que[l][0]==1){ int j,o,u,k=que[l][1]; for(j=0;j<k;j++)q[j]=pool[l][j]; q[k]=q[0]; MX=SUM=0; if(que[l][2]){ for(j=0;j<k;j++){ o=q[j]; SUM+=val[o]; up(MX,val[o]); } }else{ o=getid(q[0],q[1])<<1; u=from[o]; if(F(u)==F(0))u=from[o|1]; u=F(u); SUM=sum[u]; MX=mx[u]; for(j=0;j<k;j++){ o=q[j]; if(F(at[o])!=u){ SUM+=val[o]; up(MX,val[o]); } } } printf("%d %d\n",SUM,MX); } retrace(pos); return; } solve(l,mid,vl); solve(mid+1,r,vr); retrace(pos); } int main(){ scanf("%d%d",&Case,&n); for(i=1;i<=n;i++)scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].d); scanf("%d",&cq); if(!cq)return 0; for(i=1;i<=cq;i++){ char op[5]; scanf("%s",op); if(op[0]=='H')scanf("%d%d",&que[i][1],&que[i][2]); else{ que[i][0]=1; scanf("%d",&k); que[i][1]=k; for(j=0;j<k;j++)scanf("%d",&q[j]); q[k]=q[0]; for(j=0;j<k;j++)newedge(q[j],q[j+1]); pool[i].resize(k); for(j=0;j<k;j++)pool[i][j]=q[j]; } } for(i=0;i<m+m;i++)GetArea::g[e[i].x].insert(i); GetArea::work(); V v; for(i=1;i<=n;i++)lastv[i]=1; for(i=1;i<=cq;i++){ if(que[i][0]==0){ x=que[i][1]; y=lastv[x]; if(y<=i-1)v.push_back(EV('V',x,a[x].d,y,i-1)); a[x].d+=que[i][2]; lastv[x]=i; }else{ k=que[i][1]; for(j=0;j<k;j++)q[j]=pool[i][j]; q[k]=q[0]; ll s=0; for(j=0;j<k;j++)s+=a[q[j]]*a[q[j+1]]; if(s<0){ for(j=0;j<k;j++){ x=getid(q[j],q[j+1]); y=laste[x]; if(y+1<=i-1)v.push_back(EV('E',from[x<<1],from[x<<1|1],y+1,i-1)); laste[x]=i; } }else que[i][2]=1; } } for(i=1;i<=n;i++)v.push_back(EV('V',i,a[i].d,lastv[i],cq)); for(i=0;i<=cnt;i++)f[i]=i; for(i=0;i<m;i++){ y=laste[i]; if(y+1<=cq)v.push_back(EV('E',from[i<<1],from[i<<1|1],y+1,cq)); } solve(1,cq,v); return 0; }