P3203 [HNOI2010]弹飞绵羊(LCT维护链的size + 思维)
题目描述
某天,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的情况,你都要输出一个需要的步数,占一行。
输入输出样例
说明
对于20%的数据n,m<=10000,对于100%的数据n<=200000,m<=100000
SOLUTION:
新开一个n+1节点代表被弹飞
1 操作先把n+1换成根,access(x) ,splay(x) ,在输出x的size - 1 则是答案
2 操作就是link 然后在cut
CODE:
1 #include"bits/stdc++.h"
2 #define I inline
3 #define lson ch[x][0]
4 #define rson ch[x][1]
5 using namespace std;
6 int n,m;
7 const int N = 2e5+10;
8
9 int ch[N][2]; int fa[N];
10 int r[N];
11 int st[N],sze[N];
12
13 inline void pushr(int x)
14 {
15 swap(ch[x][0],ch[x][1]);
16 r[x]^=1;
17 }
18 inline void pushdown(int x)
19 {
20 if(r[x])
21 {
22 if(ch[x][0])pushr(ch[x][0]);
23 if(ch[x][1])pushr(ch[x][1]);
24 r[x]=0;;
25 }
26 }
27 I int pushup(int x){sze[x]=sze[lson]+1+sze[rson]; }
28 inline int nroot(int x)
29 {
30 return ch[fa[x]][0]==x||ch[fa[x]][1]==x;
31 }
32 inline void rot(int x)
33 {
34 int y=fa[x];int z=fa[y];
35 int k=ch[y][1]==x,w=ch[x][!k];
36 ch[x][!k]=y; ch[y][k]=w;
37 if(nroot(y))ch[z][ch[z][1]==y]=x;
38 if(w)fa[w]=y;fa[y]=x;fa[x]=z;
39 pushup(y);
40 }
41 inline void splay(int x)
42 {
43 int y,z=0;
44 y=x;
45 st[++z]=y;
46 while(nroot(y))st[++z]=y=fa[y];
47 while(z)pushdown(st[z--]);
48 while(nroot(x))
49 {
50 y=fa[x];z=fa[y];
51 if(nroot(y))
52 rot((ch[y][0]==x)^(ch[z][0]==z)?x:y);
53 rot(x);
54 }
55 pushup(x);
56 }
57 inline void access(int x)
58 {
59 for(int y=0;x;x=fa[y=x])
60 splay(x),ch[x][1]=y,pushup(x);
61 }
62 I int makeroot(int x)
63 {
64 access(x);splay(x);pushr(x);
65 }
66 I int findroot(int x)
67 {
68 access(x);splay(x);
69 while(ch[x][0])pushdown(x),x=ch[x][0];
70 splay(x);
71 return x;
72 }
73 I int split(int x,int y)
74 {
75 makeroot(x);
76 access(y);splay(y);
77 }
78 I int link(int x,int y)
79 {
80 makeroot(x);
81 if(findroot(y)!=x)fa[x]=y;
82 }
83 I int cut(int x,int y)
84 {
85 makeroot(x);
86 if(findroot(y)==x&&fa[y]==x&&!ch[y][0])
87 {
88 fa[y]=ch[x][1]=0; pushup(x);
89 }
90 }
91 int a[N];
92 int main()
93 {
94 cin>>n; int S=n+1;
95 for(int i=1;i<=n;i++)cin>>a[i];cin>>m;
96 for(int i=1;i<=n;i++)
97 {
98 if(i+a[i]>n)link(i,S);
99 else link(i,i+a[i]);
100 }
101 while(m--)
102 {
103 int k,l,r;cin>>k>>l;l++;
104 if(k==1)
105 {
106 makeroot(S);
107 access(l);splay(l);cout<<sze[ch[l][0]]<<endl;
108 }else
109 {
110 cin>>r;
111 cut(l,l+a[l]>n?S:l+a[l]);a[l]=r;
112 link(l,l+a[l]>n?S:l+a[l]);
113 }
114
115 }
116 }