BZOJ4764 弹飞大爷

来源:互联网 发布:大排畸b超数据分析男女 编辑:程序博客网 时间:2024/04/27 22:45

弹飞绵羊仙人掌版环套树版

lct维护动态环套树

考虑用和动态仙人掌一样的方法,给所有在环上的点都打一个环标记,值等于根的编号

这样的话在link和cut的时候各种特判然后维护环编号即可

判forever就是看根有没有环编号

注意换根之后把根换回原来的

注意cut根和根指向的环上点的情况

注意各种情况……

#include<iostream>#include<cstring>#include<ctime>#include<cmath>#include<algorithm>#include<iomanip>#include<cstdlib>#include<cstdio>#include<map>#include<bitset>#include<set>#include<stack>#include<vector>#include<queue>using namespace std;#define MAXN 200010#define MAXM 1010#define ll long long#define eps 1e-8#define MOD 1000000007#define INF 1000000000int fa[MAXN],son[MAXN][2],siz[MAXN],cir[MAXN],ch[MAXN];int st[MAXN],tp;bool rev[MAXN];int n,m;int a[MAXN];inline void ud(int x){siz[x]=siz[son[x][0]]+siz[son[x][1]]+1;}inline void torev(int x){if(!x){return ;}swap(son[x][0],son[x][1]);rev[x]^=1;}inline void toch(int x,int y){if(!x){return ;}cir[x]=ch[x]=y;}inline void pd(int x){if(rev[x]){torev(son[x][0]);torev(son[x][1]);rev[x]=0;}if(ch[x]!=-1){toch(son[x][0],ch[x]);toch(son[x][1],ch[x]);ch[x]=-1;}}inline bool ir(int x){return son[fa[x]][0]!=x&&son[fa[x]][1]!=x;}inline void cot(int x,int y,bool z){if(x){fa[x]=y;}if(y){son[y][z]=x;}}inline void rot(int x,bool z){int xx=fa[x],xxx=fa[xx];cot(son[x][z],xx,z^1);if(ir(xx)){fa[x]=xxx;}else{cot(x,xxx,son[xxx][1]==xx);}cot(xx,x,z);ud(xx);}inline void apd(int x){int i;st[++tp]=x;for(i=x;!ir(i);i=fa[i]){st[++tp]=fa[i];}for(;tp;tp--){pd(st[tp]);}}void splay(int x){apd(x);while(!ir(x)){int xx=fa[x],xxx=fa[xx];if(ir(xx)){rot(x,son[xx][0]==x);}else{bool z=son[xxx][0]==xx;if(son[xx][z]==x){rot(x,z^1);rot(x,z);}else{rot(xx,z);rot(x,z);}}}ud(x);}void acs(int x){int t=0;while(x){splay(x);son[x][1]=t;ud(x);t=x;x=fa[x];}}inline void reboot(int x){acs(x);splay(x);torev(x);}inline void link(int x,int y){reboot(x);fa[x]=y;}inline void cut(int x,int y){reboot(x);acs(y);splay(y);son[y][0]=fa[x]=0;ud(y);}int rt(int x){acs(x);splay(x);pd(x);while(son[x][0]){x=son[x][0];pd(x);}return x;}void tolink(int x,int y){if(rt(x)==rt(y)){reboot(x);acs(y);splay(y);toch(y,x);}else{link(x,y);}}void tocut(int x,int y){acs(x);splay(x);int xx=cir[x];acs(y);splay(y);int yy=cir[y];int z=rt(x);if(cir[x]&&cir[x]==cir[y]){int zz=z+a[z];acs(zz);splay(zz);toch(zz,0);if(!(x==z&&y==zz)){cut(x,y);link(z,zz);}}else{cut(x,y);reboot(z);}}int main(){int i,o,x,y;memset(ch,-1,sizeof(ch));scanf("%d%d",&n,&m);for(i=1;i<=n;i++){siz[i]=1;}for(i=1;i<=n;i++){scanf("%d",&a[i]);if(i+a[i]>=1&&i+a[i]<=n&&a[i]){tolink(i,i+a[i]);}}while(m--){scanf("%d",&o);if(o==1){scanf("%d",&x);int y=rt(x);if(cir[y]){printf("-1\n");}else{if(!a[y]){printf("-1\n");}else{printf("%d\n",siz[x]);}}}else{scanf("%d%d",&x,&y);int xx=x+a[x];if(xx<1||xx>n||!a[x]){if(!a[x]){acs(x);splay(x);toch(x,0);}a[x]=y;if(x+a[x]>=1&&x+a[x]<=n){tolink(x,x+a[x]);}}else{tocut(x,xx);a[x]=y;if(x+a[x]>=1&&x+a[x]<=n){tolink(x,x+a[x]);}}}}return 0;}/*2 3-3 42 2 02 2 21 2*/




0 0