【bzoj2002】[Hnoi2010]Bounce 弹飞绵羊 link-cut-tree

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 }

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

时间: 2024-10-31 03:32:33

【bzoj2002】[Hnoi2010]Bounce 弹飞绵羊 link-cut-tree的相关文章

[bzoj2002][Hnoi2010]Bounce弹飞绵羊_LCT

Bounce弹飞绵羊 bzoj-2002 Hnoi-2010 题目大意:n个格子,每一个格子有一个弹簧,第i个格子会将经过的绵羊往后弹k[i]个,达到i+k[i].如果i+k[i]不存在,就表示这只绵羊被弹飞了.m次操作,支持:单点修改.查询:将一只绵羊放在一个格子上问弹几次能弹飞. 注释:$1\le n \le 2\cdot 10^5$,$1\le m \le 10^5$. 想法:当场切,先容我得瑟一会儿(- ̄▽ ̄)- 说这个题,我们将i于i+k[i]连边,如果i+a[i]超过了n,就弄一个超

bzoj2002: [Hnoi2010]Bounce 弹飞绵羊 [分块][LCT]

Description 某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏.游戏一开始,Lostmonkey在地上沿着一条直线摆上n个装置,每个装置设定初始弹力系数ki,当绵羊达到第i个装置时,它会往后弹ki步,达到第i+ki个装置,若不存在第i+ki个装置,则绵羊被弹飞.绵羊想知道当它从第i个装置起步时,被弹几次后会被弹飞.为了使得游戏更有趣,Lostmonkey可以修改某个弹力装置的弹力系数,任何时候弹力系数均为正整数. Input 第一行

BZOJ2002: [Hnoi2010]Bounce 弹飞绵羊 LCT

这道题的lct不想说什么...... 这道题是lct的假板子题你需要精简并适当改进LCT给他加上不清真的属性...... #include<cstdio> #include<cstring> #define MAXN 200010 using namespace std; struct spaly { spaly *ch[2],*f; int size; void pushup() { size=ch[1]->size+ch[0]->size+1; } }null[MA

[BZOJ2002][Hnoi2010]Bounce弹飞绵羊 LCT

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2002 建图,每次往后面跳就往目标位置连边,将跳出界的点设为同一个点.对于修改操作发现可以用LCT维护图的连通性,然后用size域维护跳的点的次数就行了. 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 int inline readint(

【分块】【LCT】bzoj2002 [Hnoi2010]Bounce 弹飞绵羊

分块,每个点统计还有几步弹出该块,以及它弹出块后的下一个节点是哪个点. 注意:update某个点的时候,会可能对当前块内 该点及以前的点 产生影响,所以对这部分点进行更新. 1 #include<cstdio> 2 #include<cmath> 3 using namespace std; 4 int n,m,op,x,y,sz,a[200001],l[450],sum,num[200001],b[200001],c[200001]; 5 bool vis[200001]; 6

bzoj2002: [Hnoi2010]Bounce 弹飞绵羊

块状链表.维护一个点f[i]次能到达下一个块,和到哪个位置. #include<cstdio> #include<cmath> using namespace std; const int maxn = 400000 + 100; int k[maxn],jump[maxn],st[maxn],belong[maxn],f[maxn]; int n,m,tot=1; void build() { scanf("%d",&n); int len = (in

bzoj2002 [Hnoi2010]Bounce 弹飞绵羊【LCT】

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2002 第一道LCT,调了3天,发现是智障bug,我的青春... 主要参考了黄学长的代码,也没啥好说的,反正就是LCT,就当存一份模版好了. #include <cstdio> const int maxn = 200005; int n, m, t1, t2, t3, ori_tree_fa[maxn]; int left[maxn], right[maxn], fa[maxn], si

BZOJ 题目2002: [Hnoi2010]Bounce 弹飞绵羊(link cut tree)

2002: [Hnoi2010]Bounce 弹飞绵羊 Time Limit: 10 Sec  Memory Limit: 259 MB Submit: 5421  Solved: 2863 [Submit][Status][Discuss] Description 某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏.游戏一开始,Lostmonkey在地上沿着一条直线摆上n个装置,每个装置设定初始弹力系数ki,当绵羊达到第i个装置时,它会往后弹

【bzoj2002】[Hnoi2010]Bounce 弹飞绵羊 分块

[bzoj2002][Hnoi2010]Bounce 弹飞绵羊 2014年7月30日8101 Description 某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏.游戏一开始,Lostmonkey在地上沿着一条直线摆上n个装置,每个装置设定初始弹力系数ki,当绵羊达到第i个装置时,它会往后弹ki步,达到第i+ki个装置,若不存在第i+ki个装置,则绵羊被弹飞.绵羊想知道当它从第i个装置起步时,被弹几次后会被弹飞.为了使得游戏更有趣,Los