BZOJ2002: [Hnoi2010]Bounce 弹飞绵羊(LCT)

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 与 i 能到的点连边,yy一个不存在的点n+1,让所有点与它连边表示弹飞。

更改时先Cut后Link

最后查询时将n+1与x路径提取,查询重量即可(注意要-1^_^)

代码:

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 #define lll tr[spc].ch[0]
  5 #define rrr tr[spc].ch[1]
  6 #define ls ch[0]
  7 #define rs ch[1]
  8 const int N=300000;
  9 struct trnt{
 10     int ch[2];
 11     int lzt;
 12     int fa;
 13     int wgt;
 14     bool anc;
 15 }tr[N];
 16 int nx[N];
 17 int n,m;
 18 bool whc(int spc)
 19 {
 20     return tr[tr[spc].fa].rs==spc;
 21 }
 22 void pushup(int spc)
 23 {
 24     tr[spc].wgt=tr[lll].wgt+tr[rrr].wgt+1;
 25     return ;
 26 }
 27 void trr(int spc)
 28 {
 29     if(!spc)
 30         return ;
 31     std::swap(lll,rrr);
 32     tr[spc].lzt^=1;
 33     return ;
 34 }
 35 void pushdown(int spc)
 36 {
 37     if(tr[spc].lzt)
 38     {
 39         tr[spc].lzt=0;
 40         trr(lll);
 41         trr(rrr);
 42     }
 43     return ;
 44 }
 45 void recal(int spc)
 46 {
 47     if(!tr[spc].anc)
 48         recal(tr[spc].fa);
 49     pushdown(spc);
 50     return ;
 51 }
 52 void rotate(int spc)
 53 {
 54     int f=tr[spc].fa;
 55     bool k=whc(spc);
 56     tr[f].ch[k]=tr[spc].ch[!k];
 57     tr[spc].ch[!k]=f;
 58     if(tr[f].anc)
 59     {
 60         tr[spc].anc=1;
 61         tr[f].anc=0;
 62     }else
 63         tr[tr[f].fa].ch[whc(f)]=spc;
 64     tr[spc].fa=tr[f].fa;
 65     tr[f].fa=spc;
 66     tr[tr[f].ch[k]].fa=f;
 67     pushup(f);
 68     pushup(spc);
 69     return ;
 70 }
 71 void splay(int spc)
 72 {
 73     recal(spc);
 74     while(!tr[spc].anc)
 75     {
 76         int ft=tr[spc].fa;
 77         if(tr[ft].anc)
 78         {
 79             rotate(spc);
 80             return ;
 81         }
 82         if(whc(spc)^whc(ft))
 83             rotate(spc);
 84         else
 85             rotate(ft);
 86         rotate(spc);
 87     }
 88     return ;
 89 }
 90 void access(int spc)
 91 {
 92     int lst=0;
 93     while(spc)
 94     {
 95         splay(spc);
 96         tr[rrr].anc=1;
 97         tr[lst].anc=0;
 98         rrr=lst;
 99         pushup(spc);
100         lst=spc;
101         spc=tr[spc].fa;
102     }
103     return ;
104 }
105 void Mtr(int spc)
106 {
107     access(spc);
108     splay(spc);
109     trr(spc);
110     return ;
111 }
112 void Link(int spc,int y)
113 {
114     access(spc);
115     splay(spc);
116     tr[spc].fa=y;
117     return ;
118 }
119 void Cut(int x,int y)
120 {
121     Mtr(x);
122     access(y);
123     splay(x);
124     tr[x].rs=0;
125     tr[y].anc=1;
126     tr[y].fa=0;
127     return ;
128 }
129 void split(int x,int y)
130 {
131     Mtr(x);
132     access(y);
133     splay(y);
134 }
135 int dest(int i)
136 {
137     return (i+nx[i]>n)?(n+1):(i+nx[i]);
138 }
139 int main()
140 {
141     scanf("%d",&n);
142     for(int i=1;i<=n+1;i++)
143         tr[i].anc=1;
144     for(int i=1;i<=n;i++)
145     {
146         scanf("%d",&nx[i]);
147         Link(i,dest(i));
148     }
149     scanf("%d",&m);
150     while(m--)
151     {
152         int i,j,k;
153         scanf("%d",&i);
154         if(i==1)
155         {
156             scanf("%d",&j);
157             j++;
158             split(j,n+1);
159             printf("%d
",tr[n+1].wgt-1);
160         }else{
161             scanf("%d%d",&j,&k);
162             j++;
163             Cut(j,dest(j));
164             nx[j]=k;
165             Link(j,dest(j));
166         }
167     }
168     return 0;
169 }
原文地址:https://www.cnblogs.com/blog-Dr-J/p/9639010.html