2016-05-30 11:51:59
用一个next数组,记录点x的下一个点是哪个
查询时,moveroot(n+1),access(x),splay(x) ,输出size[ch[x][0]]即为答案
更改时,cut(x,next[x]) link(x,min(x+k,n+1))
记得splay旋转后要更新size
1 #include<bits/stdc++.h> 2 #define N 200005 3 using namespace std; 4 int read(){ 5 int x=0,f=1;char ch=getchar(); 6 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 7 while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} 8 return x*f; 9 } 10 int n,m,next[N]; 11 namespace LCT{ 12 int ch[N][2],fa[N],sz[N];bool rev[N]; 13 inline bool isroot(int x){ 14 if(ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x)return 1;return 0; 15 } 16 inline void pushdown(int x){ 17 if(rev[x]){ 18 rev[ch[x][0]]^=1;rev[ch[x][1]]^=1;rev[x]=0; 19 swap(ch[x][0],ch[x][1]); 20 } 21 } 22 inline void pushup(int x){ 23 sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+1; 24 } 25 void rotate(int x){ 26 int y=fa[x],k=ch[y][1]==x; 27 if(!isroot(y))ch[fa[y]][ch[fa[y]][1]==y]=x; 28 fa[x]=fa[y]; 29 fa[ch[x][!k]]=y; 30 fa[y]=x; 31 ch[y][k]=ch[x][!k]; 32 ch[x][!k]=y; 33 pushup(y);pushup(x); 34 } 35 void Pushdown(int x){ 36 if(!isroot(x))Pushdown(fa[x]); 37 pushdown(x); 38 } 39 void splay(int x){ 40 Pushdown(x); 41 for(int y=fa[x];!isroot(x);y=fa[x]){ 42 if(!isroot(y)){ 43 if((ch[fa[y]][ch[fa[y]][1]==y])!=(ch[y][1]==x))rotate(x); 44 else rotate(y); 45 }rotate(x); 46 } 47 } 48 inline void access(int x){ 49 int y=0; 50 while(x){ 51 splay(x); 52 ch[x][1]=y; 53 x=fa[y=x]; 54 } 55 } 56 inline void moveroot(int x){ 57 access(x);splay(x);rev[x]^=1; 58 } 59 inline void link(int x,int y){ 60 moveroot(x);fa[x]=y;splay(x); 61 } 62 inline void cut(int x,int y){ 63 moveroot(x);access(y);splay(y);ch[y][0]=fa[x]=0; 64 } 65 inline int query(int x){ 66 moveroot(n+1);access(x);splay(x); 67 return sz[ch[x][0]]; 68 } 69 } 70 int main(){ 71 n=read(); 72 for(int i=1;i<=n;i++){ 73 int x=read(); 74 LCT::fa[i]=x+i;LCT::sz[i]=1; 75 if(LCT::fa[i]>n)LCT::fa[i]=n+1; 76 next[i]=LCT::fa[i]; 77 } 78 m=read(); 79 while(m--){ 80 int t=read(); 81 if(t==1)printf("%d\n",LCT::query(read()+1)); 82 else { 83 int x=read(),y=read();x++; 84 int t=min(n+1,x+y); 85 LCT::cut(x,next[x]);LCT::link(x,t);next[x]=t; 86 } 87 } 88 return 0; 89 }
2002: [Hnoi2010]Bounce 弹飞绵羊
Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 7451 Solved: 3925
[Submit][Status][Discuss]
Description
某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏。游戏一开始,Lostmonkey在地上沿着一条直线摆上n个装置,每个装置设定初始弹力系数ki,当绵羊达到第i个装置时,它会往后弹ki步,达到第i+ki个装置,若不存在第i+ki个装置,则绵羊被弹飞。绵羊想知道当它从第i个装置起步时,被弹几次后会被弹飞。为了使得游戏更有趣,Lostmonkey可以修改某个弹力装置的弹力系数,任何时候弹力系数均为正整数。
Input
第一行包含一个整数n,表示地上有n个装置,装置的编号从0到n-1,接下来一行有n个正整数,依次为那n个装置的初始弹力系数。第三行有一个正整数m,接下来m行每行至少有两个数i、j,若i=1,你要输出从j出发被弹几次后被弹飞,若i=2则还会再输入一个正整数k,表示第j个弹力装置的系数被修改成k。对于20%的数据n,m<=10000,对于100%的数据n<=200000,m<=100000
Output
对于每个i=1的情况,你都要输出一个需要的步数,占一行。
Sample Input
4
1 2 1 1
3
1 1
2 1 1
1 1
1 2 1 1
3
1 1
2 1 1
1 1
Sample Output
2
3
3