您的位置:首页 > 其它

bzoj 2002: [Hnoi2010]Bounce 弹飞绵羊

2017-08-03 16:55 274 查看

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

Sample Output

2

3

题解:

算是简单的吧,可以用把每个弹簧看作一个点,然后LCT维护连通性即可.

如果i+a[i]>n就将i连向n+1 反之连在i+a[i]上.

修改就是先cut再link

答案就是将n+1旋到根 并且把询问点和n+1放到同一Splay中 , 深度比它小的点的个数为答案,然后显然为左子树大小

但是有个问题:gdb的时候并没有发现reserve的作用...于是发现确实没卵用..只不过修改操作要稍作变化

个人浅薄的理解为:mroot操作只是为了在cut得时候把不相关的连在一起,而这题只是cut与原父亲的连边 所以不必mroot

1RE :rotate都打错好多遍,果然还是巨水

#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
using namespace std;
const int N=200005;
int ch
[2],size
,fa
;bool rev
,rt
;
int gi(){
int str=0;char ch=getchar();
while(ch>'9' || ch<'0')ch=getchar();
while(ch>='0' && ch<='9')str=(str<<1)+(str<<3)+ch-48,ch=getchar();
return str;
}
void updata(int r){
if(!r)return ;
swap(ch[r][0],ch[r][1]);
rev[r]^=1;
}
void pushdown(int r){
if(!rev[r])return ;
updata(ch[r][0]);updata(ch[r][1]);
rev[r]=0;
}
void upsize(int r){
if(r)
size[r]=size[ch[r][1]]+size[ch[r][0]]+1;
}
void rotate(int r){
int y=fa[r];bool t=(ch[y][1]==r);
ch[y][t]=ch[r][!t];
ch[r][!t]=y;
fa[ch[y][t]]=y;
fa[r]=fa[y];
if(rt[y])
rt[y]=false,rt[r]=true;
else
ch[fa[y]][ch[fa[y]][1]==y]=r;
fa[y]=r;
upsize(y);upsize(r);
}
void Push(int r){
if(!rt[r] && r)Push(fa[r]);
pushdown(r);
}
void splay(int r){
Push(r);
while(!rt[r]){
int y=fa[r],yy=fa[y];
if(rt[y])
rotate(r);
if((ch[yy][1]==y)==(ch[y][1]==r))rotate(y),rotate(r);
else rotate(r),rotate(r);
}
pushdown(r);upsize(r);
}
void access(int x){
int y=0;
do{
splay(x);
rt[ch[x][1]]=true;rt[ch[x][1]=y]=false;
upsize(x);
x=fa[y=x];
}while(x);
}
void mroot(int x){
access(x);
splay(x);
updata(x);
}
void link(int x,int y){
mroot(x);fa[x]=y;upsize(y);
}
void cut(int x,int y){
mroot(x);access(y);splay(y);
pushdown(y);
fa[x]=ch[y][0]=0;rt[x]=true;
upsize(y);
}
int n,m,a
;
void query(int x){
mroot(n+1);
access(x);
splay(x);
printf("%d\n",size[ch[x][0]]);
}
void change(int x,int to){
if(x+a[x]<=n)cut(x,x+a[x]);
else cut(x,n+1);
a[x]=to;
if(x+a[x]<=n)link(x,x+a[x]);
else link(x,n+1);
}
int main()
{
freopen("bzoj_2002.in","r",stdin);
freopen("bzoj_2002.out","w",stdout);
int x,y,z;
n=gi();rt[0]=true;
for(int i=1;i<=n+1;i++)size[i]=1,rt[i]=true;
for(int i=1;i<=n;i++){
a[i]=gi();
if(i+a[i]<=n)link(i,i+a[i]);
else link(i,n+1);
}
m=gi();
while(m--){
x=gi();y=gi();y++;
if(x==1)query(y);
else z=gi(),change(y,z);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: