bzoj 2002: [Hnoi2010]Bounce 弹飞绵羊

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,连完之后会形成一个树结构。
  由于可以更改弹力系数,所以树边之间存在断开和连接的操作,就是用动态树来完成。
  1 #include<iostream>
  2 #include<cstdlib>
  3 #include<cstdio>
  4 #include<cmath>
  5 #include<algorithm>
  6 #include<queue>
  7 #include<vector>
  8 using namespace std;
  9 const int N=200005;
 10 inline int read(){
 11     int x=0,f=1;char ch=getchar();
 12     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
 13     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
 14     return x*f;
 15 }
 16 int n,m;
 17 int next[N],c[N][2],fa[N],size[N],st[N];
 18 bool rev[N];
 19 bool isroot(int x){
 20     return x!=c[fa[x]][0]&&x!=c[fa[x]][1];
 21 }
 22 void pushup(int x){
 23     size[x]=size[c[x][0]]+size[c[x][1]]+1;
 24 }
 25 void pushdown(int x){
 26     int l=c[x][0],r=c[x][1];
 27     if(rev[x]==true){
 28         rev[x]^=1; rev[l]^=1; rev[r]^=1;
 29         swap(c[x][0],c[x][1]);
 30     }
 31 }
 32 void rotate(int x){
 33     int y=fa[x],z=fa[y],l,r;
 34     if(x==c[y][0]) l=0;else l=1; r=l^1;
 35     if(!isroot(y)){
 36         if(y==c[z][0]) c[z][0]=x;
 37         else c[z][1]=x;
 38     }
 39     fa[x]=z; fa[y]=x; fa[c[x][r]]=y;
 40     c[y][l]=c[x][r]; c[x][r]=y;
 41     pushup(y); pushdown(x);
 42 }
 43 void splay(int x){
 44     int top=0; st[++top]=x;
 45     for(int i=x;isroot(i)==false;i=fa[i]){
 46         st[++top]=fa[i];
 47     }
 48     for(int i=top;i;i--) pushdown(st[i]);
 49     while(!isroot(x)){
 50         int y=fa[x],z=fa[y];
 51         if(!isroot(y)){
 52             if((x==c[y][0]&&y==c[z][0])||(x==c[y][1]&&y==c[z][1])){
 53                 rotate(y),rotate(x);
 54             }
 55             else rotate(x),rotate(x);
 56         }
 57         else rotate(x);
 58     }
 59 }
 60 void access(int x){
 61     int t=0;
 62     while(x!=0){
 63         splay(x);
 64         c[x][1]=t;
 65         t=x; x=fa[x];
 66     }
 67 }
 68 void rever(int x){
 69     access(x); splay(x); rev[x]^=1;
 70 }
 71 void cut(int x,int y){
 72     rever(x); access(y); splay(y); c[y][0]=fa[x]=0;
 73 }
 74 void link(int x,int y){
 75     rever(x); fa[x]=y; splay(x);
 76 }
 77 int main(){
 78     n=read();
 79     for(int i=1;i<=n;i++){
 80           int x=read();
 81         fa[i]=x+i; size[i]=1;
 82         if(fa[i]>n+1) fa[i]=n+1;
 83         next[i]=fa[i];
 84     }
 85     size[n+1]=1;
 86     m=read();
 87     for(int i=1;i<=m;i++){
 88         int f=read();
 89         if(f==1){
 90             rever(n+1);
 91             int x=read(); x++;
 92             access(x);
 93             splay(x);
 94             printf("%d
",size[c[x][0]]);
 95         }
 96         else{
 97             int x=read(),y=read(); x++;
 98             int t=min(n+1,x+y);
 99             cut(x,next[x]);
100             link(x,t);
101             next[x]=t;
102         }
103     }
104     return 0;
105 }
   
 
原文地址:https://www.cnblogs.com/CXCXCXC/p/5190048.html