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;
}
}
}