BZOJ 1453 [Wc]Dface双面棋盘
#include<iostream> #include<cstdio> #include<cstring> using namespace std; const int maxn=100009; const int oo=1000000000; int dx[5]={0,1,0,0,-1}; int dy[5]={0,0,-1,1,0}; int n,TT; int cntedge; int fa[maxn]={0},ch[maxn][2]={0},siz[maxn],ky[maxn]={0},mn[maxn]={0},mnp[maxn]={0},rev[maxn]={0}; inline int son(int x){ if(ch[fa[x]][0]==x)return 0; else return 1; } inline void pushup(int x){ mn[x]=ky[x];mnp[x]=x; if(mn[ch[x][0]]<mn[x]){ mn[x]=mn[ch[x][0]]; mnp[x]=mnp[ch[x][0]]; } if(mn[ch[x][1]]<mn[x]){ mn[x]=mn[ch[x][1]]; mnp[x]=mnp[ch[x][1]]; } siz[x]=siz[ch[x][0]]+siz[ch[x][1]]+(ky[x]==oo); } inline void pushdown(int x){ if(rev[x]){ rev[ch[x][0]]^=1; rev[ch[x][1]]^=1; rev[x]^=1; swap(ch[x][0],ch[x][1]); } } inline bool isroot(int x){ return (ch[fa[x]][0]!=x)&&(ch[fa[x]][1]!=x); } void Downfa(int x){ if(!isroot(x))Downfa(fa[x]); pushdown(x); } inline void Rotate(int x){ int y=fa[x]; int z=fa[y]; int b=son(x),c=son(y); int a=ch[x][b^1]; if(!isroot(y))ch[z][c]=x; fa[x]=z; if(a)fa[a]=y; ch[y][b]=a; fa[y]=x;ch[x][b^1]=y; pushup(y);pushup(x); } void Splay(int x){ Downfa(x); while(!isroot(x)){ int y=fa[x]; if(isroot(y)){ Rotate(x); }else{ if(son(x)==son(y)){ Rotate(y);Rotate(x); }else{ Rotate(x);Rotate(x); } } } } void Acc(int x){ for(int t=0;x;t=x,x=fa[x]){ Splay(x);ch[x][1]=t;pushup(x); } } void Makeroot(int x){ Acc(x);Splay(x);rev[x]^=1; } void Lin(int x,int y){ Makeroot(x);fa[x]=y; } void Cut(int x,int y){ Makeroot(x);Acc(y);Splay(y); fa[ch[y][0]]=0;ch[y][0]=0;pushup(y); } int Getroot(int x){ Acc(x);Splay(x); while(ch[x][0])x=ch[x][0]; return x; } int GetminEdge(int x,int y){ Makeroot(x);Acc(y);Splay(y); return mnp[y]; } int p[209][209]; int OG[209][209]; int a[209][209]; int opt[maxn][3]; int ans[maxn][3]; int nex[maxn]; int tong[maxn]; int nowans; void MakeLink(int x,int y){ int lastest=min(tong[x],tong[y]); if(Getroot(x)!=Getroot(y)){ // cout<<x<<' '<<y<<endl; --nowans;++cntedge; mn[cntedge]=ky[cntedge]=lastest; mnp[cntedge]=cntedge; Lin(x,cntedge);Lin(y,cntedge); }else{ int tm=GetminEdge(x,y); // cout<<tm<<endl; if(ky[tm]>=lastest)return; Cut(x,tm);Cut(y,tm); ++cntedge; mn[cntedge]=ky[cntedge]=lastest; mnp[cntedge]=cntedge; // cout<<x<<' '<<y<<endl; Lin(x,cntedge);Lin(y,cntedge); } } int HaveEdge(int x,int y){ if(Getroot(x)!=Getroot(y))return 0; Makeroot(x);Acc(y); Splay(y); int tm=siz[ch[y][0]]; Splay(x); int tm2=siz[ch[x][0]]; if(tm2==tm-1)return 1; else return 0; } void MakeCut(int x,int y){ if(!HaveEdge(x,y))return; Cut(x,y); nowans++; } inline int Isright(int x,int y){ if((x<=0)||(y<=0))return 0; if((x>n)||(y>n))return 0; return 1; } void Sol1(){ ky[0]=mn[0]=oo; nowans=0; cntedge=n*n; for(int i=1;i<=n;++i){ for(int j=1;j<=n;++j){ a[i][j]=OG[i][j]; if(a[i][j])++nowans; } } for(int i=1;i<=n*n;++i)tong[i]=oo-1; for(int i=1;i<=n*n;++i){ siz[i]=1;mn[i]=ky[i]=oo; } for(int i=TT;i>=1;--i){ tong[p[opt[i][1]][opt[i][2]]]=i; } for(int i=1;i<=n;++i){ for(int j=1;j<=n;++j){ if(a[i][j]!=1)continue; for(int k=1;k<=2;++k){ int x=i+dx[k]; int y=j+dy[k]; if(!Isright(x,y))continue; if(a[x][y]!=1)continue; MakeLink(p[x][y],p[i][j]); } } } for(int i=1;i<=TT;++i){ int x=opt[i][1],y=opt[i][2]; if(a[x][y]==0){ a[x][y]=1; tong[p[x][y]]=nex[i]; ++nowans; for(int k=1;k<=4;++k){ int xx=x+dx[k]; int yy=y+dy[k]; if(!Isright(xx,yy))continue; if(!a[xx][yy])continue; MakeLink(p[x][y],p[xx][yy]); } }else{ a[x][y]=0; tong[p[x][y]]=nex[i]; for(int k=1;k<=4;++k){ int xx=x+dx[k]; int yy=y+dy[k]; if(!Isright(xx,yy))continue; if(!a[xx][yy])continue; MakeCut(p[x][y],p[xx][yy]); } --nowans; } ans[i][1]=nowans; } } void Sol2(){ memset(fa,0,sizeof(fa)); memset(ch,0,sizeof(ch)); memset(ky,0,sizeof(ky)); memset(mn,0,sizeof(mn)); memset(mnp,0,sizeof(mnp)); memset(rev,0,sizeof(rev)); ky[0]=mn[0]=oo; nowans=0; cntedge=n*n; for(int i=1;i<=n;++i){ for(int j=1;j<=n;++j){ a[i][j]=OG[i][j]; if(a[i][j]==0)++nowans; } } for(int i=1;i<=n*n;++i)tong[i]=oo-1; for(int i=1;i<=n*n;++i){ siz[i]=1;mn[i]=ky[i]=oo; } for(int i=TT;i>=1;--i){ tong[p[opt[i][1]][opt[i][2]]]=i; } for(int i=1;i<=n;++i){ for(int j=1;j<=n;++j){ if(a[i][j])continue; for(int k=1;k<=2;++k){ int x=i+dx[k]; int y=j+dy[k]; if(!Isright(x,y))continue; if(a[x][y])continue; // cout<<"fucking "<<p[x][y]<<' '<<p[i][j]<<endl; MakeLink(p[x][y],p[i][j]); } } } // cout<<"begin"<<endl; for(int i=1;i<=TT;++i){ int x=opt[i][1],y=opt[i][2]; if(a[x][y]){ a[x][y]=0; tong[p[x][y]]=nex[i]; ++nowans; for(int k=1;k<=4;++k){ int xx=x+dx[k]; int yy=y+dy[k]; if(!Isright(xx,yy))continue; if(a[xx][yy])continue; MakeLink(p[x][y],p[xx][yy]); } }else{ a[x][y]=1; tong[p[x][y]]=nex[i]; for(int k=1;k<=4;++k){ int xx=x+dx[k]; int yy=y+dy[k]; if(!Isright(xx,yy))continue; if(a[xx][yy])continue; MakeCut(p[x][y],p[xx][yy]); } --nowans; } ans[i][2]=nowans; } } int main(){ scanf("%d",&n); for(int cnt=0,i=1;i<=n;++i){ for(int j=1;j<=n;++j){ p[i][j]=++cnt; } } for(int i=1;i<=n;++i){ for(int j=1;j<=n;++j){ scanf("%d",&OG[i][j]); } } scanf("%d",&TT); for(int i=1;i<=TT;++i){ int x,y; scanf("%d%d",&x,&y); opt[i][1]=x;opt[i][2]=y; if(tong[p[x][y]])nex[tong[p[x][y]]]=i; tong[p[x][y]]=i; } for(int i=1;i<=TT;++i)if(nex[i]==0)nex[i]=oo-1; Sol1(); Sol2(); for(int i=1;i<=TT;++i)printf("%d %d\n",ans[i][1],ans[i][2]); return 0; }
题解:
动态图的连通性问题
离线下来,维护边权为删除时间的最大生成树
在知乎上看了一篇很好的文章,先留坑,以后补上
致歉:笔者已经意识到这是一篇几乎没有价值的文章,给您的阅读带来不好的体验,并且干扰了您的搜索环境,非常抱歉!