BZOJ 2002: [Hnoi2010]Bounce 弹飞绵羊
2002: [Hnoi2010]Bounce 弹飞绵羊
Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 9803 Solved: 5055
[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
HINT
Source
分析:
一道LCT板子题目...
就是维护到根节点路径的长度...
代码:
#include<algorithm> #include<iostream> #include<cstring> #include<cstdio> //by NeighThorn using namespace std; const int maxn=200000+5; int n,m,pos[maxn]; struct M{ int dis; bool reverse; M *son[2],*father; inline M(void){ dis=1; father=NULL; reverse=false; son[0]=son[1]=NULL; } inline void update(void){ dis=1; if(son[0]) dis+=son[0]->dis; if(son[1]) dis+=son[1]->dis; } inline bool isroot(void){ if(father==NULL) return true; if(father->son[0]==this) return false; if(father->son[1]==this) return false; return true; } inline void pushdown(void){ if(reverse){ reverse=false; swap(son[0],son[1]); if(son[0]) son[0]->reverse^=true; if(son[1]) son[1]->reverse^=true; } } }tr[maxn]; inline void connect(M *f,M *t,int k){ if(t!=NULL) t->father=f; if(f!=NULL) f->son[k]=t; } inline void rotate(M *t){ M *f=t->father; M *g=f->father; bool s=(f->son[1]==t); connect(f,t->son[!s],s); connect(t,f,!s); t->father=g; if(g&&g->son[0]==f) g->son[0]=t; if(g&&g->son[1]==f) g->son[1]=t; f->update(); t->update(); } inline void push(M *t){ static M *stk[maxn]; int top=0; stk[top++]=t; while(!t->isroot()) stk[top++]=t=t->father; while(top) stk[--top]->pushdown(); } inline void splay(M *t){ push(t); while(!t->isroot()){ M *f=t->father; M *g=f->father; if(f->isroot()) rotate(t); else{ bool a=(f&&f->son[1]==t); bool b=(g&&g->son[1]==f); if(a==b) rotate(f),rotate(t); else rotate(t),rotate(t); } } } inline void access(M *t){ M *p=NULL; while(t!=NULL){ splay(t); t->son[1]=p,t->update(); p=t,t=t->father; } } inline void makeroot(M *t){ access(t),splay(t),t->reverse^=true; } inline void link(M *f,M *t){ makeroot(t),t->father=f; } inline void cut(M *t){ splay(t); if(t->son[1]) t->son[1]->father=NULL; if(t->son[0]) t->son[0]->father=NULL; t->son[0]=t->son[1]=NULL,t->update(); } inline M *find(M *t){ access(t); splay(t); M *r=t; while(r->son[0]) r=r->son[0]; return r; } signed main(void){ scanf("%d",&n); for(int i=0;i<=n;i++) tr[i]=M(); for(int i=1,x;i<=n;i++) scanf("%d",&x),link(tr+(pos[i]=x+i>n?0:x+i),tr+i); scanf("%d",&m); for(int q=1,opt,x,k;q<=m;q++){ scanf("%d%d",&opt,&x);x++; if(opt==1){ makeroot(tr+0); access(tr+x); splay(tr+x); printf("%d\n",tr[x].dis-1); } else{ scanf("%d",&k); makeroot(tr+pos[x]);access(tr+x); splay(tr+x);cut(tr+x); link(tr+(pos[x]=x+k>n?0:x+k),tr+x); } } return 0; }
By NeighThorn