bzoj 2002
2002: [Hnoi2010]Bounce 弹飞绵羊
Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 3848 Solved: 2051
[Submit][Status]
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
我的第一题LCT。现在仍理解得不是很透彻。
LCT:通过access操作把一棵树分解成若干条路径,用splay维护路径的信息,使复杂度达到logN级别
这题只有两个操作:
1.询问某节点的深点
2.修改某个节点的父亲
只用了access操作.
继续努力吧。LCT还要多写几题啊.
#include<cstdio> #include<cstdlib> #include<algorithm> #include<cmath> #include<cstring> using namespace std; //fa[i],i如果不是splay的根,则表示i在splay中的父节点,否则表示i所splay表示的链连接的树中的父节点 //root[i],表示i是否是splay的根 struct tree{ int ls,rs; }tr[200011]; int fa[200011],size[200011]; bool root[200011]; int i,n,x,z,kind,m; void update(int x) { size[x]=size[tr[x].ls]+size[tr[x].rs]+1; } void right_rotate(int x) { int y,z; y=tr[x].ls; z=tr[y].rs; tr[x].ls=z; tr[y].rs=x; fa[z]=x; if(tr[fa[x]].ls==x)tr[fa[x]].ls=y; if(tr[fa[x]].rs==x)tr[fa[x]].rs=y; fa[y]=fa[x]; fa[x]=y; if(root[x]==true){ root[y]=true; root[x]=false; } update(x); update(y); } void left_rotate(int x) { int y,z; y=tr[x].rs; z=tr[y].ls; tr[x].rs=z; tr[y].ls=x; fa[z]=x; if(tr[fa[x]].ls==x)tr[fa[x]].ls=y; if(tr[fa[x]].rs==x)tr[fa[x]].rs=y; fa[y]=fa[x]; fa[x]=y; if(root[x]==true){ root[y]=true; root[x]=false; } update(x); update(y); } void splay(int x) { while(root[x]==false){ if(tr[fa[x]].rs==x)left_rotate(fa[x]); else right_rotate(fa[x]); } } void access(int x) { int z; splay(x); while(fa[x]!=0){ z=fa[x]; splay(z); root[tr[z].rs]=true; root[x]=false; tr[z].rs=x; update(z); x=z; splay(x); } } int main() { memset(root,true,sizeof(root)); scanf("%d",&n); for(i=1;i<=n;i++){ scanf("%d",&x); fa[i]=i+x; if(fa[i]>n)fa[i]=n+1; } for(i=1;i<=n+1;i++)size[i]=1; scanf("%d",&m); for(i=1;i<=m;i++){ scanf("%d",&kind); if(kind==1){ scanf("%d",&x); x++; access(x); splay(x); printf("%d\n",size[tr[x].ls]); } else{ scanf("%d%d",&x,&z); x++; access(x); splay(x); fa[tr[x].ls]=fa[x]; root[tr[x].ls]=true; tr[x].ls=0; size[x]=size[tr[x].rs]+1; fa[x]=x+z; if(fa[x]>n)fa[x]=n+1; } } }