Bzoj2002 [Hnoi2010]Bounce 弹飞绵羊

Time Limit: 10 Sec  Memory Limit: 259 MB
Submit: 9355  Solved: 4816

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

HINT

 

Source

 

树 LCT

每个位置当成一个结点,维护一棵Link-cut tree

将代表出界的点0置为根。如果一个点x可以弹跳到另一个点y,就连接x和y;如果从x会弹飞,就连接x和0

回答询问时,先access(x),看x左子树的size(也就是x的father的数量)就知道需要弹多少次了。

 

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<algorithm>
  4 #include<cstring>
  5 #include<queue>
  6 using namespace std;
  7 const int mxn=200010;
  8 int read(){
  9     int x=0,f=1;char ch=getchar();
 10     while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
 11     while(ch>='0' && ch<='9'){x=x*10-'0'+ch;ch=getchar();}
 12     return x*f;
 13 }
 14 int n,m;
 15 struct node{
 16     int ch[2];
 17     int sz,fa;
 18     bool rt;
 19 }t[mxn];
 20 void init(){
 21     for(int i=1;i<=n;i++){t[i].sz=1;t[i].rt=1;}
 22     return;
 23 }
 24 void pushup(int rt){
 25     t[rt].sz=t[t[rt].ch[0]].sz+t[t[rt].ch[1]].sz+1;
 26     return;
 27 }
 28 void rotate(int x){
 29     int y=t[x].fa;int z=t[y].fa,lc,rc;
 30     if(t[y].ch[0]==x)lc=0;else lc=1; rc=lc^1;
 31     if(t[y].rt){
 32         t[y].rt=0;t[x].rt=1;
 33     }
 34     else t[z].ch[t[z].ch[1]==y]=x;
 35     t[x].fa=z;t[y].ch[lc]=t[x].ch[rc];
 36     t[t[x].ch[rc]].fa=y;t[x].ch[rc]=y;
 37     t[y].fa=x;
 38     pushup(y);
 39     return;
 40 }
 41 void Splay(int x){
 42     while(!t[x].rt){
 43         int y=t[x].fa;int z=t[y].fa;
 44         if(t[y].rt)rotate(x);
 45         else{
 46             if((t[y].ch[0]==x)^(t[z].ch[0]==y))rotate(x);
 47                 else rotate(y);
 48             rotate(x);
 49         }
 50     }
 51     pushup(x);
 52     return;
 53 }
 54 void access(int x){//访问x 
 55     int y=0;
 56     while(x){
 57         Splay(x);
 58         t[t[x].ch[1]].rt=1;t[y].rt=0;//切断x原来的右子树 
 59         t[x].ch[1]=y;//当前点连接被访问点 
 60         pushup(x);
 61         y=x;x=t[x].fa;//上溯 
 62     }
 63 }
 64 void find(int x){
 65     access(x);
 66     Splay(x);
 67 }
 68 void link(int x,int y){
 69     find(x);
 70     t[t[x].ch[0]].fa=0;
 71     t[t[x].ch[0]].rt=1;
 72     t[x].ch[0]=0;
 73     t[x].fa=y;
 74     pushup(x);
 75     return;
 76 }
 77 int main(){
 78     int i,j,k,u,v;
 79     n=read();
 80     init();
 81     for(i=1;i<=n;i++){
 82         k=read();
 83         if(i+k<=n)link(i,i+k);
 84     }
 85     m=read();
 86     while(m--){
 87         k=read();
 88         if(k==1){
 89             u=read()+1;//编号整体+1 
 90             find(u);
 91             printf("%d\n",t[t[u].ch[0]].sz+1);
 92         }
 93         else{
 94             u=read()+1;k=read();
 95             if(u+k>n)link(u,0);
 96             else link(u,u+k);
 97         }
 98     }
 99     return 0;
100 }

 

posted @ 2017-02-02 17:47  SilverNebula  阅读(124)  评论(0编辑  收藏
AmazingCounters.com