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

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


直接模拟肯定超时

考虑分块优化

(其实是不会lct辣!)

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<cmath>
 5 using namespace std;
 6
 7 inline int read(){
 8     char ch;
 9     int re=0;
10     bool flag=0;
11     while((ch=getchar())!=‘-‘&&(ch<‘0‘||ch>‘9‘));
12     ch==‘-‘?flag=1:re=ch-‘0‘;
13     while((ch=getchar())>=‘0‘&&ch<=‘9‘)  re=re*10+ch-‘0‘;
14     return flag?-re:re;
15 }
16
17 const int maxn=200001;
18
19 int n,m;
20 //b[][1]跳到下一分块中的位置
21 //b[][0]跳到下一分块需要的步数
22 //c[]分块序号
23 int a[maxn],b[maxn][2],c[maxn];
24
25 int main(){
26     //freopen("temp.in","r",stdin);
27     n=read();
28     for(int i=0;i<n;i++)  a[i]=read();
29     for(int i=0,v=1,h=(int)sqrt(n);i<n;i++){
30         c[i]=v;
31         if((i+1)%h==0)  v++;
32     }
33     for(int i=n-1;i>=0;i--){
34         //跳出分块或弹飞
35         if(i+a[i]>n-1||c[i+a[i]]!=c[i])  b[i][1]=i+a[i];
36         else  b[i][1]=b[i+a[i]][1];
37         //记录多少步跳出分块
38         if(c[i+a[i]]!=c[i])  b[i][0]=1;
39         else  b[i][0]=b[i+a[i]][0]+1;
40     }
41     m=read();
42     int opt,pos,num,ans;
43     while(m--){
44         opt=read();
45         if(opt==1){
46             pos=read();
47             ans=0;
48             while(pos<=n-1){
49                 ans+=b[pos][0];
50                 pos=b[pos][1];
51             }
52             if(ans==0)  puts("1");
53             else  printf("%d\n",ans);
54         }
55         else{
56             pos=read();  num=read();
57             a[pos]=num;
58             if(pos+num>n-1||c[pos+num]!=c[pos])  b[pos][1]=pos+num;
59             else  b[pos][1]=b[pos+num][1];
60             if(c[pos+num]!=c[pos])  b[pos][0]=1;
61             else  b[pos][0]=b[pos+num][0]+1;
62             for(int i=pos-1;i>=0;i--){
63                 if(c[i]!=c[pos])  break;
64                 if(i+a[i]<=n-1&&c[i+a[i]]==c[i])  b[i][1]=b[i+a[i]][1];
65                 if(c[i+a[i]]==c[i])  b[i][0]=b[i+a[i]][0]+1;
66             }
67         }
68     }
69     return 0;
70 }

时间: 2024-12-28 14:57:47

bzoj2002: [Hnoi2010]Bounce 弹飞绵羊 [分块][LCT]的相关文章

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 弹飞绵羊(lct)

(BZOJ挂了,还没在BZOJ测,先是在wikioi测过了,,) 囧.在军训时立志要学lct!!!这是一道lct的裸题,只有access操作(10行都没有啊亲...缩行大法的话,我就不说了..)(link操作相当于水过),其实lct很简单..想想都有点小激动...... lct用splay维护的话,一下就写好了..但是我在写lct的时候,发现了一些我原来splay的老问题,我原来也知道了的,就是将null的ch给赋值了,因为在rot操作里没有特判,所以导致了null的孩子被赋值了,导致我的lct

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

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

bzoj 2002 : [Hnoi2010]Bounce 弹飞绵羊 (LCT)

链接:https://www.lydsy.com/JudgeOnline/problem.php?id=2002 题面: 2002: [Hnoi2010]Bounce 弹飞绵羊 Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 15763  Solved: 8080[Submit][Status][Discuss] Description 某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏.游戏一开

[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,就弄一个超

B2002 [Hnoi2010]Bounce 弹飞绵羊 分块

原来做过,看大家都做这道题都热情高涨,沈爷爷debug这道题4天,作为告诉他这个题的人,我还有点不好意思...我自己也就做了一个小时. 其实这个题思路还好,就是维护每个点的出块次数和跳出块的位置,然后访问的时候直接调用块. 这个题还有一个比较坑的地方,就是每个绵羊只有到队尾的时候才会被弹飞,所以不用担心在中间停止的情况. 题干: Description 某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏.游戏一开始,Lostmonkey在地上沿

【分块】【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弹飞绵羊 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(

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