P3203 [HNOI2010]彈飛綿羊(LCT)
阿新 • • 發佈:2018-12-03
思路
首先在每個彈力裝置和它能到達的彈力裝置處連邊
會發現長的像一顆樹一樣
然後涉及到了修改,就是動態的連邊和刪除邊,可以想到用LCT維護
然後對於修改,cut掉原來的邊,再link新的節點即可
查詢把(j,x+10)split出來,然後x+10節點中存放的就是需要的資訊,去掉本身的sz就是1之後就是答案
程式碼
#include <cstdio> #include <algorithm> #include <cstring> using namespace std; struct SPT{ int son[2],sz,tag; }SPT[200100]; int fa[200100],n,a[200100],m; void pushup(int o){ SPT[o].sz=SPT[SPT[o].son[0]].sz+SPT[SPT[o].son[1]].sz+1; } void pushdown(int o){ if(o&&SPT[o].tag){ SPT[SPT[o].son[0]].tag^=1; SPT[SPT[o].son[1]].tag^=1; swap(SPT[o].son[0],SPT[o].son[1]); SPT[o].tag=0; } } bool isrl(int o){ return o==SPT[fa[o]].son[1]; } bool isroot(int o){ return (SPT[fa[o]].son[0]!=o)&&(SPT[fa[o]].son[1]!=o); } void rorate(int o){ if(isroot(o)) return; int f=fa[o]; int g=fa[f]; int which=isrl(o); pushdown(f); pushdown(o); //o--g fa[o]=g; if(!isroot(f)) SPT[g].son[SPT[g].son[1]==f]=o; // fa[SPT[o].son[which^1]]=f; SPT[f].son[which]=SPT[o].son[which^1]; SPT[o].son[which^1]=f; fa[f]=o; pushup(f); pushup(o); } void push(int o){ if(!isroot(o)) push(fa[o]); pushdown(o); } void splay(int o){ push(o); for(int f;!isroot(o);rorate(o)){ if(!isroot(f=fa[o])) rorate((isrl(f)==isrl(o))?f:o); } } void access(int o){ for(int y=0;o;o=fa[y=o]) splay(o),SPT[o].son[1]=y,pushup(o); } void makeroot(int o){ access(o); splay(o); SPT[o].tag^=1; pushdown(o); } int findroot(int o){ access(o); splay(o); pushdown(o); while(SPT[o].son[0]) pushdown(o=SPT[o].son[0]); return o; } void split(int x,int y){ makeroot(x); access(y); splay(y); } void link(int x,int y){ makeroot(x); if(findroot(y)!=x) fa[x]=y; } void cut(int x,int y){ makeroot(x); if(findroot(y)==x&&fa[x]==y&&SPT[y].son[0]==x&&SPT[x].son[1]==0) fa[x]=0,SPT[y].son[0]=0,pushup(y); } int main(){ scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d",&a[i]); SPT[i].sz=1; } SPT[n+10].sz=1; for(int i=1;i<=n;i++) link(i,(i+a[i]>n)?n+10:i+a[i]); scanf("%d",&m); for(int i=1;i<=m;i++){ int opt,j,k; scanf("%d %d",&opt,&j); j++; if(opt==1){ split(j,n+10); printf("%d\n",SPT[n+10].sz-1); } else{ scanf("%d",&k); cut(j,(j+a[j]>n)?n+10:j+a[j]); a[j]=k; link(j,(j+a[j]>n)?n+10:j+a[j]); } } }