您的位置:首页 > 其它

bzoj 2002: [Hnoi2010]Bounce 弹飞绵羊

2016-02-15 10:32 351 查看
Time Limit: 10 Sec  Memory Limit: 259 MB
Submit: 6521  Solved: 3420
[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


1 2 1 1
3
1 1
2 1 1
1 1

Sample Output

2
3   题解:       如果绵羊能从i跳到j,则连一条由i连向j的边,如果能被弹飞,连向n+1,连完之后会形成一个树结构。   由于可以更改弹力系数,所以树边之间存在断开和连接的操作,就是用动态树来完成。
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;
const int N=200005;
inline int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int n,m;
int next
,c
[2],fa
,size
,st
;
bool rev
;
bool isroot(int x){
return x!=c[fa[x]][0]&&x!=c[fa[x]][1];
}
void pushup(int x){
size[x]=size[c[x][0]]+size[c[x][1]]+1;
}
void pushdown(int x){
int l=c[x][0],r=c[x][1];
if(rev[x]==true){
rev[x]^=1; rev[l]^=1; rev[r]^=1;
swap(c[x][0],c[x][1]);
}
}
void rotate(int x){
int y=fa[x],z=fa[y],l,r;
if(x==c[y][0]) l=0;else l=1; r=l^1;
if(!isroot(y)){
if(y==c[z][0]) c[z][0]=x;
else c[z][1]=x;
}
fa[x]=z; fa[y]=x; fa[c[x][r]]=y;
c[y][l]=c[x][r]; c[x][r]=y;
pushup(y); pushdown(x);
}
void splay(int x){
int top=0; st[++top]=x;
for(int i=x;isroot(i)==false;i=fa[i]){
st[++top]=fa[i];
}
for(int i=top;i;i--) pushdown(st[i]);
while(!isroot(x)){
int y=fa[x],z=fa[y];
if(!isroot(y)){
if((x==c[y][0]&&y==c[z][0])||(x==c[y][1]&&y==c[z][1])){
rotate(y),rotate(x);
}
else rotate(x),rotate(x);
}
else rotate(x);
}
}
void access(int x){
int t=0;
while(x!=0){
splay(x);
c[x][1]=t;
t=x; x=fa[x];
}
}
void rever(int x){
access(x); splay(x); rev[x]^=1;
}
void cut(int x,int y){
rever(x); access(y); splay(y); c[y][0]=fa[x]=0;
}
void link(int x,int y){
rever(x); fa[x]=y; splay(x);
}
int main(){
n=read();
for(int i=1;i<=n;i++){
int x=read();
fa[i]=x+i; size[i]=1;
if(fa[i]>n+1) fa[i]=n+1;
next[i]=fa[i];
}
size[n+1]=1;
m=read();
for(int i=1;i<=m;i++){
int f=read();
if(f==1){
rever(n+1);
int x=read(); x++;
access(x);
splay(x);
printf("%d\n",size[c[x][0]]);
}
else{
int x=read(),y=read(); x++;
int t=min(n+1,x+y);
cut(x,next[x]);
link(x,t);
next[x]=t;
}
}
return 0;
}

 

     
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: