Luogu 3203 BZOJ 2002——弹飞绵羊
题意概括
给定一个序列,有N个装置,绵羊在不同
其实就是个裸LCT。
从i能跳到i+k即可以理解为i到i+k之间有一条连边
修改操作即断边然后连边。
在查询时只需要把要出发的点成为原树的根,然后访问n+1,把n+1splay到根,然后结果就在n+1的子树中了。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<cstdio> #include<algorithm> #define maxn 200100 using namespace std; struct TREE{ int c[2],sum,fa,rev; }tree[maxn]; int stack[maxn],n,a[maxn]; int read(){ int w=0;char c=getchar(); while(c<'0'||c>'9') c=getchar(); while(c>='0'&&c<='9') w=w*10+c-48,c=getchar(); return w; } inline void update(int x){ tree[x].sum=tree[tree[x].c[0]].sum+tree[tree[x].c[1]].sum+1; } inline void pushdown(int x){ if(!tree[x].rev) return; int l=tree[x].c[0],r=tree[x].c[1]; if(l) tree[l].rev^=1; if(r) tree[r].rev^=1; swap(tree[x].c[0],tree[x].c[1]); tree[x].rev^=1; } bool isroot(int x){ return tree[tree[x].fa].c[0]!=x&&tree[tree[x].fa].c[1]!=x; } bool get(int x) { return x==tree[tree[x].fa].c[1];} void rotate(int x){ int f=tree[x].fa,ff=tree[tree[x].fa].fa,opt=get(x); tree[f].c[opt]=tree[x].c[opt^1]; tree[tree[x].c[opt^1]].fa=f; if(!isroot(f)) tree[ff].c[get(f)]=x; tree[x].fa=ff;tree[f].fa=x; tree[x].c[opt^1]=f; update(f);update(x); } void splay(int x){ int top=0,tmp=x;stack[++top]=x; while(!isroot(tmp))stack[++top]=tree[tmp].fa,tmp=tree[tmp].fa; while(top)pushdown(stack[top]),top--; while(!isroot(x)){ rotate(x); } } void access(int x){ int son=0; while(x){ splay(x);tree[x].c[1]=son; update(x);son=x;x=tree[x].fa; } } void makeroot(int x){ access(x);splay(x);tree[x].rev^=1; } void link(int x,int y){ makeroot(x);tree[x].fa=y; splay(x); } void cut(int x,int y){ makeroot(x);access(y); splay(y);tree[y].c[0]=tree[x].fa=0; } int query(int x,int y){ makeroot(x);access(y);splay(y); return tree[y].sum; } int getfa(int x){ access(x);splay(x); while(tree[x].c[0]){ pushdown(x);x=tree[x].c[0]; splay(x); } return x; } void change(int x,int y){ makeroot(x); // tree[x].val=y; update(x); } void answer(int i){ makeroot(i); access(n+1); splay(n+1); // printf("1"); printf("%d ",tree[n+1].sum-1); } int main(){ int x,i,opt,m,k; n=read(); for(i=1;i<=n;i++){ x=a[i]=read(); if(i+x<=n) link(i,i+x); else link(i,n+1); } m=read(); for(i=1;i<=m;i++){ opt=read();x=read()+1; if(opt==1) answer(x); else {k=read();if(a[x]+x<=n)cut(x,a[x]+x);else cut(x,n+1); if(x+k<=n)link(x,x+k);else link(x,n+1);a[x]=k;} } }