洛谷P3203 [HNOI2010]彈飛綿羊
阿新 • • 發佈:2019-02-02
hup pda pre std 輸入格式 find amp print spl ,表示地上有n個裝置,裝置的編號從\(0\)到\(n-1\)。
接下來一行有\(n\)個正整數,依次為那\(n\)個裝置的初始彈力系數。
第三行有一個正整數\(m\),
接下來\(m\)行每行至少有兩個數\(i、j\),若\(i=1\),你要輸出從j出發被彈幾次後被彈飛,若\(i=2\)則還會再輸入一個正整數\(k\),表示第\(j\)個彈力裝置的系數被修改成\(k\)。 號點變成實鏈,然後把第\(n+1\)號點splay到樹頂,這是\(n+1\)號點的左子樹的大小就是需要彈的次數。
洛谷P3203 [HNOI2010]彈飛綿羊
題目描述
某天,Lostmonkey發明了一種超級彈力裝置,為了在他的綿羊朋友面前顯擺,他邀請小綿羊一起玩個遊戲。遊戲一開始,Lostmonkey在地上沿著一條直線擺上\(n\)個裝置,每個裝置設定初始彈力系數\(k_i\),當綿羊達到第i個裝置時,它會往後彈\(k_i\)步,達到第\(i+k_i\)個裝置,若不存在第\(i+k_i\)個裝置,則綿羊被彈飛。綿羊想知道當它從第\(i\)個裝置起步時,被彈幾次後會被彈飛。為了使得遊戲更有趣,Lostmonkey可以修改某個彈力裝置的彈力系數,任何時候彈力系數均為正整數。
輸入輸出格式
輸入格式:
第一行包含一個整數\(n\)
接下來一行有\(n\)個正整數,依次為那\(n\)個裝置的初始彈力系數。
第三行有一個正整數\(m\),
接下來\(m\)行每行至少有兩個數\(i、j\),若\(i=1\),你要輸出從j出發被彈幾次後被彈飛,若\(i=2\)則還會再輸入一個正整數\(k\),表示第\(j\)個彈力裝置的系數被修改成\(k\)。
輸出格式:
對於每個\(i=1\)的情況,你都要輸出一個需要的步數,占一行。
思路
動態樹
在初始狀態下,建立動態樹,將每一個節點和通過他會彈到的節點連起來,所有會彈飛的節點都連向一個\(n+1\)號點。
對於每一個修改操作,將修改的節點和他原來會彈到的節點之間斷開,然後將它連向新的會彈到的節點。
對於每一個查詢操作,將查詢的節點和\(n+1\)
CODE
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; #define MAXN 200010 int ch[MAXN][2],fa[MAXN],cur[MAXN],sz[MAXN]; int q[MAXN]; bool rev[MAXN]; int i,j,k,m,n,x,y,qtop; char readc; void read(int &n){ while((readc=getchar())<48||readc>57); n=readc-48; while((readc=getchar())>=48&&readc<=57) n=n*10+readc-48; } int get(int x){ return ch[fa[x]][1]==x; } bool isroot(int x){ return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x; } void pushup(int x){ sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+1; } void pushdown(int x){ if(rev[x]){ swap(ch[x][0],ch[x][1]); rev[ch[x][0]]^=1,rev[ch[x][1]]^=1; rev[x]=false; } } void rotate(int x){ int y=fa[x],z=fa[y],k=get(x),w=ch[x][k^1]; ch[y][k]=w,fa[w]=y; if(!isroot(y)) ch[z][get(y)]=x; fa[x]=z; ch[x][k^1]=y,fa[y]=x; pushup(y),pushup(x); } void splay(int x){ qtop=1; q[qtop]=x; for(int i=x;!isroot(i);i=fa[i]) q[++qtop]=fa[i]; for(int i=qtop;i>=1;i--) pushdown(q[i]); while(!isroot(x)){ int y=fa[x]; if(!isroot(y)){ if(get(x)==get(y)) rotate(y); else rotate(x); } rotate(x); } pushup(x); } void access(int x){ for(int y=0;x;y=x,x=fa[x]){ splay(x),ch[x][1]=y; pushup(x); } } void makeroot(int x){ access(x); splay(x); rev[x]^=1; } int findroot(int x){ access(x); splay(x); while(ch[x][0]) pushdown(x),x=ch[x][0]; return x; } 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; pushup(y); } void cut(int x,int y){ makeroot(x); access(y); if(findroot(y)==x&&fa[x]==y&&ch[x][1]==0){ fa[x]=0,ch[y][0]=0; pushup(y); } } int query(int x){ split(x,n+1); return sz[ch[n+1][0]]; } void update(int x,int y){ int z=min(n+1,x+y); cut(x,cur[x]); link(x,z); cur[x]=z; } int main(){ read(n); for(i=1;i<=n;i++) read(cur[i]),sz[i]=1; sz[n+1]=1; for(i=1;i<=n;i++){ k=min(n+1,i+cur[i]); cur[i]=k; link(i,k); } read(m); for(i=1;i<=m;i++){ read(x); read(y); if(x==1){ printf("%d\n",query(y+1)); }else{ read(k); update(y+1,k); } } return 0; }
洛谷P3203 [HNOI2010]彈飛綿羊