【[HNOI2010]弹飞绵羊】LCT乱搞题
最近新学了LCT,又可以刷一堆水(keng)题了,真是开心啊
传送门: https://www.luogu.org/problemnew/show/P3203
感觉还是很显然吧,直接将这个(点)与(点+劲度系数)的点连接起来,
同时考虑建一个空结点n+1(编号0不好处理,于是所有编号向上平移一个单位),意为所有的绵羊到这个地方就能够被弹飞
如果连接的时候i+k<=n就连不然就和n+1连接起来
每一次询问操作,setroot(x) access(n+1) splay(n+1),答案就是siz[n+1]-1
而每次进行修改劲度系数的时候,不只是光要连,还要将原来的边删掉。 就可以了(同时记得编号连接不大于n+1规定)
就这样搞定了,开始痛苦地调试罢!
cheer!
#include<bits/stdc++.h> #define zig(x) zigzag(x,1) #define zag(x) zigzag(x,2) using namespace std; const int maxn=200005; int n,m,rev[maxn],ls[maxn],rs[maxn],fa[maxn],jingdu[maxn],siz[maxn]; bool isroot(int x) { return ls[fa[x]]!=x&&rs[fa[x]]!=x; } void putup(int x) { siz[x]=siz[ls[x]]+siz[rs[x]]+1; } void zigzag(int x,int knd) { int y=fa[x],z=fa[y]; if(!isroot(y)) { if(ls[z]==y) ls[z]=x; else rs[z]=x; } fa[x]=z; fa[y]=x; if(knd==1) { ls[y]=rs[x]; fa[ls[y]]=y; rs[x]=y; } else { rs[y]=ls[x]; fa[rs[y]]=y; ls[x]=y; } putup(y); putup(x); } void putdowm(int x) { if(!rev[x]) return; swap(ls[x],rs[x]); rev[ls[x]]^=1; rev[rs[x]]^=1; rev[x]=0; } int sta[maxn]; void splay(int x) { int top=0; sta[++top]=x; for(int i=x;!isroot(i);i=fa[i]) { sta[++top]=fa[i]; } while(top) putdowm(sta[top--]); while(!isroot(x)) { int y=fa[x],z=fa[y]; if(isroot(y)) { if(ls[y]==x) zig(x); else zag(x); } else { if(ls[z]==y) { if(ls[y]==x) { zig(y); zig(x); } else { zag(x); zig(x); } } else { if(rs[y]==x) { zag(y); zag(x); } else { zig(x); zag(x); } } } } } void acc(int x) { for(int y=0;x;y=x,x=fa[x]) { splay(x); rs[x]=y; putup(x); } } void setroot(int x) { acc(x); splay(x); rev[x]^=1; } void link(int a,int b) { setroot(a); fa[a]=b; } void cut(int a,int b) { setroot(a); acc(b); splay(b); ls[b]=fa[a]=0; } int getroot(int a) { acc(a); splay(a); while(ls[a]) a=ls[a]; return a; } int ans(int x) { setroot(x); acc(n+1); splay(n+1); return siz[n+1]-1; } void change(int x,int y) { cut(x,min(jingdu[x]+x,n+1)); jingdu[x]=y; link(x,min(x+jingdu[x],n+1)); } int main() { int x,y,z; scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&jingdu[i]); link(i,min(jingdu[i]+i,n+1)); } scanf("%d",&m); for(int i=1;i<=m;i++) { scanf("%d",&x); if(x==1) { scanf("%d",&y); ++y; printf("%d\n",ans(y)); } else { scanf("%d%d",&y,&z); ++y; change(y,z); } } }