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;
}

  

上一篇:Java项目开启远程调试(tomcat、springboot)


下一篇:(转)JAVA AJAX教程第三章—AJAX详细讲解