洛谷P3203 [HNOI2010] 弹飞绵羊 [LCT]

  题目传送门

弹飞绵羊

题目描述

某天,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。

 

输出格式:

 

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

 

输入输出样例

输入样例#1: 
4
1 2 1 1
3
1 1
2 1 1
1 1
输出样例#1: 
2
3

说明

对于20%的数据n,m<=10000,对于100%的数据n<=200000,m<=100000


  分析:

  把每个装置看作一个点,然后连边,每次修改弹力值就可以看作断边和连边,可以用LCT维护。那么查询显然就直接求该点原树到根节点的距离。维护的时候比较方便,很多函数都可以省略。

  Code:

 1 //It is made by HolseLee on 30th June 2018
 2 //Luogu.org P3203
 3 #include<bits/stdc++.h>
 4 using namespace std;
 5 const int N=2e5+7;
 6 int n,m,a[N],fa[N],s[N],ch[N][2];
 7 inline int read()
 8 {
 9     char ch=getchar();int num=0;bool flag=false;
10     while(ch<'0'||ch>'9'){if(ch=='-')flag=true;ch=getchar();}
11     while(ch>='0'&&ch<='9'){num=num*10+ch-'0';ch=getchar();}
12     return flag?-num:num;
13 }
14 inline void pushup(int x)
15 {
16     s[x]=s[ch[x][0]]+s[ch[x][1]]+1;
17 }
18 inline bool isroot(int x)
19 {
20     return (ch[fa[x]][0]!=x)&&(ch[fa[x]][1]!=x);
21 }
22 inline void rotate(int x)
23 {
24     int y=fa[x],z=fa[y];    
25     int k=(ch[y][1]==x);
26     int w=ch[x][k^1];
27     if(!isroot(y))ch[z][ch[z][1]==y]=x;
28     ch[x][k^1]=y;ch[y][k]=w;
29     if(w)fa[w]=y;fa[y]=x;fa[x]=z;
30     pushup(y);
31 }
32 inline void splay(int x)
33 {
34     while(!isroot(x)){
35         int y=fa[x],z=fa[y];
36         if(!isroot(y))
37         ((ch[y][0]==x)^(ch[z][0]==y))?
38         rotate(y):rotate(x);
39         rotate(x);}
40     pushup(x);
41 }
42 inline void access(int x)
43 {
44     for(int y=0;x;x=fa[y=x])
45     splay(x),ch[x][1]=y,pushup(x);
46 }
47 int main()
48 {
49     n=read();int x,y,z;
50     for(int i=1;i<=n;i++){
51         s[i]=1;x=read();
52         if(i+x<=n)fa[i]=i+x;}
53     m=read();
54     for(int i=1;i<=m;i++){
55         x=read();y=read();
56         if(x==1){
57             ++y;
58             access(y);splay(y);
59             printf("%d\n",s[y]);
60         }
61         else{
62             z=read();++y;
63             access(y);splay(y);
64             ch[y][0]=fa[ch[y][0]]=0;
65             if(y+z<=n)fa[y]=y+z;
66             pushup(y);}
67     }
68     return 0;
69 }

猜你喜欢

转载自www.cnblogs.com/cytus/p/9247679.html