题目链接
Description
某天,(Lostmonkey)发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏。游戏一开始,(Lostmonkey)在地上沿着一条直线摆上n个装置,每个装置设定初始弹力系数(k_i),当绵羊达到第i个装置时,它会往后弹(k_i)步,达到第(i+k_i)个装置,若不存在第(i+k_i)个装置,则绵羊被弹飞。绵羊想知道当它从第(i)个装置起步时,被弹几次后会被弹飞。为了使得游戏更有趣,(Lostmonkey)可以修改某个弹力装置的弹力系数,任何时候弹力系数均为正整数。
思路
分块,维护:
- 每个点跳几次跳到下一个块
- 跳到下一个块的什么位置
初始化:(O(n))
修改:(O(sqrt n))
查询:(O(sqrt n))
Code
#include <bits/stdc++.h>
#define F(i, a, b) for (int i = (a); i < (b); ++i)
#define F2(i, a, b) for (int i = (a); i <= (b); ++i)
#define dF(i, a, b) for (int i = (a); i > (b); --i)
#define dF2(i, a, b) for (int i = (a); i >= (b); --i)
#define maxn 200010
using namespace std;
typedef long long LL;
int a[maxn], n, blo, bl[maxn], num;
struct node { int cnt, p; }v[maxn];
void init() {
F(i, 0, num) {
int ed = min((i+1)*blo-1, n-1),
st = i*blo;
dF2(j, ed, st) {
int ne = j+a[j];
if (ne>ed) v[j] = {1, ne};
else v[j] = v[ne], ++v[j].cnt;
}
}
}
void modify(int x, int c) {
a[x] = c;
int st = bl[x]*blo, ed = min((bl[x]+1)*blo-1, n-1);
dF2(i, x, st) {
int ne = i+a[i];
if (ne > ed) v[i] = {1, ne};
else v[i] = v[ne], ++v[i].cnt;
}
}
int query(int x) {
int ret=0;
while (x < n) {
ret += v[x].cnt;
x = v[x].p;
}
return ret;
}
int main() {
scanf("%d", &n); blo = sqrt(n);
F(i, 0, n) {
scanf("%d", &a[i]);
bl[i] = i/blo;
}
num = bl[n-1]+1;
init();
int m;
scanf("%d", &m);
F(i, 0, m) {
int op, x, y;
scanf("%d", &op);
if (op==1) {
scanf("%d",&x);
printf("%d
", query(x));
}
else {
scanf("%d%d", &x,&y);
modify(x,y);
}
}
return 0;
}