bzoj 2002 Bounce 弹飞绵羊(分块)

2002: [Hnoi2010]Bounce 弹飞绵羊

Time Limit: 10 Sec  Memory Limit: 259 MB
Submit: 11202  Solved: 5698
[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

HINT

Source

题解:

  有n 个装置,我们可以将它们分成 √n 块。

  对于在一块内,如果i + ki > n (直接弹飞)next = -1(没有下个个了), ans = 1(需要一步就被弹飞),

  如果i +ki > 这个块的最后一个, next = i+ki (弹到下一个块), ans = 1(我们认为弹到下一个块一步)

  如果i + ki 在这个块内, 那么next = next[i+ki] (在这个块内的 i 我要他能后跳到下一个块的位置), ans = ans[i+ki] + 1(这个很好理解)。

  对于询问的 位置x, 只会一个块一个块的跳,(因为有next[i] = next[i+ki] 直到有一个位置是跳出这一块)

  对于修改我们只需要将这个块的修改一下(块个块之间是相对独立的),而不用修改n个。(将修改的位置到这个块的位置更新一下就可以了)。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <string>
 5 #include <algorithm>
 6 #include <cmath>
 7 #include <vector>
 8 #include <queue>
 9 #include <map>
10 #include <stack>
11 #include <set>
12 using namespace std;
13 typedef long long LL;
14 #define ms(a, b) memset(a, b, sizeof(a))
15 #define pb push_back
16 #define mp make_pair
17 const int INF = 0x7fffffff;
18 const int inf = 0x3f3f3f3f;
19 const LL mod = 2147493647;
20 const int maxn = 200000+10;
21 int next[maxn], k[maxn], ans[maxn];
22 void init() {
23     ms(k,0);
24 }
25 void solve() {
26     int n, unit, m, op, wei;
27     scanf("%d", &n);
28     for(int i = 0;i<n;i++)  scanf("%d", &k[i]);
29     unit = (int)sqrt(n);
30     for(int i = n-1;i>=0;i--){
31         int temp = i + k[i];
32         if(temp >= n){
33             next[i] = -1;ans[i] = 1;
34         }
35         else if(temp >= (i/unit+1)*unit ){
36             next[i] = temp;
37             ans[i] = 1;
38         }
39         else{
40             next[i] = next[temp];
41             ans[i] = ans[temp] + 1;
42         }
43     }
44     scanf("%d", &m);
45     while(m--){
46         scanf("%d%d", &op, &wei);
47         if(op==1){
48             int Ans = 0;
49             for(int i = wei;~i;i=next[i])
50                 Ans+=ans[i];
51             printf("%d\n", Ans);
52         }
53         else{
54             int k2;
55             scanf("%d", &k2);
56             k[wei] = k2;
57             for(int i = wei;i>=wei/unit*unit;i--){
58                 int temp = i + k[i];
59                 if(temp >= n){
60                     next[i] = -1;ans[i] = 1;
61                 }
62                 else if(temp >= (i/unit+1)*unit){
63                     next[i] = temp;
64                     ans[i] = 1;
65                 }
66                 else{
67                     next[i] = next[temp];
68                     ans[i] = ans[temp] + 1;
69                 }
70             }
71
72         }
73     }
74 }
75 int main() {
76 #ifdef LOCAL
77     freopen("input.txt", "r", stdin);
78 //        freopen("output.txt", "w", stdout);
79 #endif
80     init();
81     solve();
82     return 0;
83 }

时间: 2024-10-13 16:20:03

bzoj 2002 Bounce 弹飞绵羊(分块)的相关文章

BZOJ 2002 Bounce 弹飞绵羊(分块|暴力|)(困难)

Bounce 弹飞绵羊 Time Limit:10000MS     Memory Limit:265216KB     64bit IO Format:%lld & %llu Submit Status Practice HYSBZ 2002 Description 某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏.游戏一开始,Lostmonkey在地上沿着一条直线摆上n个装置,每个装置设定初始弹力系数ki,当绵羊达到第i个装置时,它会往后

BZOJ 2002 HNOI2010 弹飞绵羊 分块

题目大意及LCT版本题解:见 http://blog.csdn.net/popoqqq/article/details/38849471 今天手滑用分块又重写了一遍这道题0.0 分块就是短啊 将弹簧分为√n块 对于每个弹簧 我们记录一下从这个弹簧出发直到弹到块外为止的弹跳次数及落点 查询沿着落点弹到出去为止 修改从块开始到这个点为止修改一遍 这样修改和查询都是O(√n)的 #include<cmath> #include<cstdio> #include<cstring>

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

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

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

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

B2002 [Hnoi2010]Bounce 弹飞绵羊 分块

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

BZOJ 2002: [Hnoi2010]Bounce 弹飞绵羊 分块

http://www.lydsy.com/JudgeOnline/problem.php?id=2002 维护cnt[i]表示第i个节点,跳出他所属于的块的最小步数, to[i]表示第i个节点,跳出他所属的块的时候,去到那一个位置. 那么, 查询:复杂度O(sqrt(n)),不断   ans += cnt[i]   然后   i  = to[i]即可. 更新:分块这种东西,跟新都是块内更新的,块间都是独立的. 更新第id个东西,可以知道是不影响后面的.而且如果我知道第id个跳去了那个块,步数也可

[BZOJ2002] Bounce 弹飞绵羊(分块)

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2002 1 #include <bits/stdc++.h> 2 using namespace std; 3 #define fr first 4 #define sc second 5 #define cl clear 6 #define BUG puts("here!!!") 7 #define W(a) while(a--) 8 #define pb(a) p

【BZOJ】2002: [Hnoi2010]Bounce 弹飞绵羊(lct)

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