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的情况,你都要输出一个需要的步数,占一行。

 

输入输出样例

输入样例#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

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 }
原文地址:https://www.cnblogs.com/zhangbuang/p/11158209.html