1. 程式人生 > >bzoj4764: 彈飛大爺 link-cut-tree

bzoj4764: 彈飛大爺 link-cut-tree

target cnblogs else pre ace 奇怪 using 寫法 splay

題目傳送門

這道題啊 調了一個晚上 因為寫的是一個有根樹和n個基環的寫法 所以寫得很奇怪..... 最後發現單獨處理樹的時候不能隨意改變S(就是原來的根)不然size會出錯....

技術分享
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
const int M=250007;
int read(){
    int ans=0,f=1,c=getchar();
    while(c<0||c>9){if
(c==-) f=-1; c=getchar();} while(c>=0&&c<=9){ans=ans*10+(c-0); c=getchar();} return ans*f; } int c[M][2],fa[M],size[M],rev[M],lx[M],rx[M],sum[M]; int n,m; bool isrt(int x){return c[fa[x]][0]!=x&&c[fa[x]][1]!=x;} void up(int x){size[x]=size[c[x][0]]+size[c[x][1]]+1;}
void down(int x){ //printf("~~~%d\n",x); int l=c[x][0],r=c[x][1]; if(rev[x]){ if(l) swap(c[l][0],c[l][1]),rev[l]^=1; if(r) swap(c[r][0],c[r][1]),rev[r]^=1; rev[x]=0; } int u=lx[x],v=rx[x]; if(l) lx[l]=u,rx[l]=v; if(r) lx[r]=u,rx[r]=v; } void rotate(int x){
int y=fa[x],z=fa[y],l=0,r=1; if(c[y][1]==x) l=1,r=0; if(!isrt(y)) c[z][c[z][1]==y]=x; fa[y]=x; fa[x]=z; fa[c[x][r]]=y; c[y][l]=c[x][r]; c[x][r]=y; up(y); up(x); } int st[M],top=0,S; void test() { cout<<"No "<<endl; for (int j=1;j<=n+1;j++) cout<<j<<" son"<<c[j][0]<< <<c[j][1]<<" fa"<<fa[j]<<" rev"<<rev[j]<<" size"<<size[j]<<" edge"<<lx[j] <<rx[j]<<endl;cout<<endl; } void splay(int x){ st[++top]=x; for(int i=x;!isrt(i);i=fa[i]) st[++top]=fa[i]; while(top) down(st[top--]); while(!isrt(x)){ int y=fa[x],z=fa[y]; if(!isrt(y)){ if(c[z][0]==y^c[y][0]==x) rotate(x); else rotate(y); } rotate(x); } } void acs(int x0){ for(int x=x0,y=0;x;splay(x),c[x][1]=y,up(x),y=x,x=fa[x]); splay(x0); } void mrt(int x){acs(x); swap(c[x][0],c[x][1]); rev[x]^=1;} int find(int x){ acs(x); while(c[x][0]) x=c[x][0]; return x; } void push_link(int x,int y){mrt(x); fa[x]=y; acs(x);} void link(int x,int y){ if(find(x)==find(y)) lx[y]=x,rx[y]=y; else push_link(x,y);//printf("%d %d\n",x,y); } //void dfs(int x){ // if(!x) return ; // printf("~~~%d\n",x); // dfs(c[x][0]); // dfs(c[x][1]); //} int push_ans(int x){ acs(x); if(lx[x]&&rx[x]) return -1; //dfs(x); return size[x]-1; } void cut(int x,int y){mrt(x); acs(y); /*cout<<"cuttest2"<<endl;test();*/c[y][0]=fa[x]=0; up(y); lx[x]=rx[x]=lx[y]=rx[y]=0;} void push_cut(int x,int y){ acs(x); int l=lx[x],r=rx[x]; if(l==x&&r==y) lx[x]=rx[x]=0; else{ cut(x,y); //printf("%d %d\n",x,y); if(l&&r) link(l,r); } } int main() { int k,x,w; n=read(); m=read(); S=n+1; for(int i=1;i<=S;i++) size[i]=1; for(int i=1;i<=n;i++){ k=read(); sum[i]=k; if(i+k<=0||i+k>n) push_link(i,S); else link(i,i+k); } for(int i=1;i<=m;i++){ k=read(); if(k==1) x=read(),mrt(S),printf("%d\n",push_ans(x)); else{ x=read(); w=read(); if(x+sum[x]<=0||x+sum[x]>n) cut(x,S); else push_cut(x,x+sum[x]);//printf("~%d %d\n",x,x+sum[x]); // cout<<"cutfinish"<<endl;test(); if(x+w<=0||x+w>n) push_link(x,S); //printf("~~~\n"); else link(x,x+w);//printf("%d %d\n",x,x+w); sum[x]=w; } //test(); } return 0; }
View Code

bzoj4764: 彈飛大爺 link-cut-tree