wjyi

人这么弱,有什么资格颓废(ಥ _ ಥ)

  博客园  :: 首页  :: 新随笔  :: 联系 ::  :: 管理

2016-05-30 11:51:59

用一个next数组,记录点x的下一个点是哪个

查询时,moveroot(n+1),access(x),splay(x) ,输出size[ch[x][0]]即为答案

更改时,cut(x,next[x]) link(x,min(x+k,n+1))

记得splay旋转后要更新size

 1 #include<bits/stdc++.h>
 2 #define N 200005
 3 using namespace std;
 4 int read(){
 5   int x=0,f=1;char ch=getchar();
 6   while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
 7   while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
 8   return x*f;
 9 }
10 int n,m,next[N];
11 namespace LCT{
12   int ch[N][2],fa[N],sz[N];bool rev[N];
13   inline bool isroot(int x){
14     if(ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x)return 1;return 0;
15   }
16   inline void pushdown(int x){
17     if(rev[x]){
18       rev[ch[x][0]]^=1;rev[ch[x][1]]^=1;rev[x]=0;
19       swap(ch[x][0],ch[x][1]);
20     }
21   }
22   inline void pushup(int x){
23     sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+1;
24   }
25   void rotate(int x){
26     int y=fa[x],k=ch[y][1]==x;
27     if(!isroot(y))ch[fa[y]][ch[fa[y]][1]==y]=x;
28     fa[x]=fa[y];
29     fa[ch[x][!k]]=y;
30     fa[y]=x;
31     ch[y][k]=ch[x][!k];
32     ch[x][!k]=y;
33     pushup(y);pushup(x);
34   }
35   void Pushdown(int x){
36     if(!isroot(x))Pushdown(fa[x]);
37     pushdown(x);
38   }
39   void splay(int x){
40       Pushdown(x);
41       for(int y=fa[x];!isroot(x);y=fa[x]){
42         if(!isroot(y)){
43             if((ch[fa[y]][ch[fa[y]][1]==y])!=(ch[y][1]==x))rotate(x);
44             else rotate(y);
45         }rotate(x);
46     }
47   }
48   inline void access(int x){
49     int y=0;
50     while(x){
51       splay(x);
52       ch[x][1]=y;
53       x=fa[y=x];
54     }
55   }
56   inline void moveroot(int x){
57     access(x);splay(x);rev[x]^=1;
58   }
59   inline void link(int x,int y){
60       moveroot(x);fa[x]=y;splay(x);
61   }
62   inline void cut(int x,int y){
63       moveroot(x);access(y);splay(y);ch[y][0]=fa[x]=0;
64   }
65   inline int query(int x){
66       moveroot(n+1);access(x);splay(x);
67       return sz[ch[x][0]];
68   }
69 }
70 int main(){
71   n=read();
72   for(int i=1;i<=n;i++){
73     int x=read();
74     LCT::fa[i]=x+i;LCT::sz[i]=1;
75     if(LCT::fa[i]>n)LCT::fa[i]=n+1;
76     next[i]=LCT::fa[i];
77   }
78   m=read();
79   while(m--){
80     int t=read();
81     if(t==1)printf("%d\n",LCT::query(read()+1));
82     else {
83       int x=read(),y=read();x++;
84       int t=min(n+1,x+y);
85       LCT::cut(x,next[x]);LCT::link(x,t);next[x]=t;
86     }
87   }
88   return 0;
89 }
View Code

2002: [Hnoi2010]Bounce 弹飞绵羊

Time Limit: 10 Sec  Memory Limit: 259 MB
Submit: 7451  Solved: 3925
[Submit][Status][Discuss]

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

 

posted on 2016-05-30 11:56  wjyi  阅读(107)  评论(0编辑  收藏