BZOJ2002 [HNOI2010]弹飞绵羊

【问题描述】

某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏。游戏一开始,Lostmonkey在地上沿 着一条直线摆上n个装置,每个装置设定初始弹力系数ki,当绵羊达到第i个装置时,它会往后弹ki步,达到第i+ki个装置,若不存在第i+ki个装置, 则绵羊被弹飞。绵羊想知道当它从第i个装置起步时,被弹几次后会被弹飞。为了使得游戏更有趣,Lostmonkey可以修改某个弹力装置的弹力系数,任何 时候弹力系数均为正整数。

【输入格式】

第一行包含一个整数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

【输出格式】

对于每个i=1的情况,你都要输出一个需要的步数,占一行。

【输入样例】

4
1 2 1 1
3
1 1
2 1 1
1 1

【输出样例】

2
3

 

正解:LCT

解题报告:直接用动态树维护,然后在splay里面维护一个子树的大小size就可以了。

  1 #include <iostream>
  2 #include <iomanip>
  3 #include <string>
  4 #include <algorithm>
  5 #include <cmath>
  6 #include <cstring>
  7 #include <cstdlib>
  8 #include <cstdio>
  9 #define RG register
 10 const int N = 300000;
 11  
 12 using namespace std;
 13  
 14 int gi(){
 15     char ch=getchar();int x=0;
 16     while(ch<'0' || ch>'9') ch=getchar();
 17     while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
 18     return x;
 19 }
 20  
 21 int n,m,f[N],fa[N],rev[N],c[N][2],st[N],nx[N],siz[N];
 22  
 23 int isroot(int x){
 24     return c[fa[x]][0]!=x && c[fa[x]][1]!=x;
 25 }
 26  
 27 void pushdown(int x){
 28     if (rev[x]==0) return;
 29     RG int l=c[x][0],r=c[x][1];
 30     rev[x]^=1,rev[l]^=1,rev[r]^=1;
 31     swap(c[x][0],c[x][1]);
 32     return;
 33 }
 34  
 35 void pushsum(int x){
 36     siz[x]=siz[c[x][0]]+siz[c[x][1]]+1;
 37     return;
 38 }
 39  
 40 void rotate(int x){
 41     RG int l,r,y=fa[x],z=fa[y];
 42     if (c[y][0]==x) l=0;
 43     else l=1;r=l^1;
 44     if (!isroot(y))
 45         if (c[z][0]==y) c[z][0]=x;
 46         else c[z][1]=x;
 47     fa[c[x][r]]=y,fa[y]=x,fa[x]=z;
 48     c[y][l]=c[x][r],c[x][r]=y;
 49     pushsum(y),pushsum(x);
 50     return;
 51 }
 52  
 53 void splay(int x){
 54     RG int tot=0;
 55     st[++tot]=x;
 56     for (RG int i=x; !isroot(i); i=fa[i]) st[++tot]=fa[i];
 57     for (RG int i=tot; i; --i) pushdown(st[i]);
 58     while(!isroot(x)){
 59         RG int y=fa[x],z=fa[y];
 60         if (!isroot(y))
 61             if (c[y][0]==x ^ c[z][0]==y) rotate(x);
 62             else rotate(y);
 63         rotate(x);
 64     }
 65     return;
 66 }
 67  
 68 void access(int x){
 69     int t=0;
 70     while(x){
 71         splay(x);
 72         c[x][1]=t;
 73         t=x,x=fa[x];
 74     }
 75     return;
 76 }
 77  
 78 void rever(int x){
 79     access(x),splay(x),rev[x]^=1;
 80     return;
 81 }
 82  
 83 void cut(int x,int y){
 84     rever(x),access(y),splay(y);
 85     c[y][0]=fa[x]=0;
 86     return;
 87 }
 88  
 89 void link(int x,int y){
 90     rever(x);
 91     fa[x]=y;
 92     return;
 93 }
 94  
 95 int main(){
 96     n=gi();RG int s,l,r;siz[n+1]=1;
 97     for (RG int i=1; i<=n; ++i) f[i]=gi(),siz[i]=1;m=gi();
 98     for (RG int i=1; i<=n; ++i) nx[i]=i+f[i]<=n?i+f[i]:n+1;
 99     for (RG int i=1; i<=n; i++) fa[i]=nx[i];
100     for (RG int i=1; i<=m; i++){
101         s=gi(),l=gi()+1;
102         if (s==1){
103             rever(n+1);
104             access(l);
105             splay(l);
106             printf("%d\n",siz[c[l][0]]);
107         }
108         else{
109             cut(l,nx[l]);
110             r=gi(),nx[l]=l+r<=n?l+r:n+1;
111             link(l,nx[l]);
112         }
113     }
114     return 0;
115 }

 

posted @ 2017-02-18 22:10  Cjk_2001  阅读(169)  评论(0编辑  收藏  举报