描述
- Lostmonkey在地上沿着一条直线摆上n个装置,每个装置设定初始弹力系数ki,当绵羊达到第i个装置时,它会往后弹ki步,达到第i+ki个装置,若不存在第i+ki个装置,则绵羊被弹飞。绵羊想知道当它从第i个装置起步时,被弹几次后会被弹飞。为了使得游戏更有趣,Lostmonkey可以修改某个弹力装置的弹力系数,任何时候弹力系数均为正整数。
分析
- 分块, 维护 i 位置的绵羊经过几次弹出该块(f[]), 以及弹出后落在哪个位置(arv[]). 这样就可以在 n√n 的时间内完成本题.
- 遇到查询操作, 则每次 ans 加上 f[i], i 转移到 arv[i], 直到 arv[i] ≥ n
- 遇到修改操作, 则只需维护 该块的 f[] 数组和 arv[] 数组.
- 维护时不用一个点一个点的计算, 而是从后向前倒推.
- 我练习了一下对拍和生成数据, 靠对拍发现了错误.
#include
#include
using namespace std;
const int maxn = 200000 + 10;
const int maxb = 500 + 10;
int A[maxn], f[maxn], arv[maxn];
int L[maxb], R[maxb];
int main() {
int n, m, size, block;
scanf("%d", &n);
for(int i = 0; i < n; i++) scanf("%d", &A[i]);
size = (int)sqrt(n);
block = n/size + (n%size != 0); //
for(int b = 0; b < block; b++) {
L[b] = b*size;
R[b] = (b+1)*size-1;
}
R[block-1] = n-1;
for(int b = 0; b < block; b++)
for(int i = R[b]; i >= L[b]; i--) {
int j = i + A[i];
if(j > R[b]) f[i] = 1, arv[i] = j;
else f[i] = f[j] + 1, arv[i] = arv[j];
}
scanf("%d", &m);
while(m--) {
int k, x, b;
scanf("%d %d", &k, &x);
b = x/size;
if(k == 1) {
int ans = 0;
while(x < n) ans += f[x], x = arv[x];
printf("%d\n", ans);
} else {
scanf("%d", &A[x]);
for(int i = R[b]; i >= L[b]; i--) {
int j = i + A[i];
if(j > R[b]) f[i] = 1, arv[i] = j;
else f[i] = f[j] + 1, arv[i] = arv[j];
}
}
}
return 0;
}
#include
#include
using namespace std;
int main() {
freopen("bzoj_2002.in", "w", stdout);
// freopen("bzoj_2002.out", "r", stdin);
srand(0);
int n = 100, m = 100;
printf("%d\n", n);
for(int i = 1; i <= n; i++) printf("%d ", rand() % 9 + 1);
printf("%d\n", m);
for(int i = 1; i <= m; i++) {
int k = rand() % 2 + 1;
if(k == 1) {
printf("%d %d\n", k, rand() % n);
} else {
printf("%d %d %d\n", k, rand() % n, rand() % 9 + 1);
}
}
return 0;
}
#include
#include
using namespace std; const int maxn = 200000 + 10; const int maxb = 500 + 10; int A[maxn], f[maxn], arv[maxn]; int L[maxb], R[maxb]; int main() { freopen("bzoj_2002.in", "r", stdin); freopen("bzoj_2002_force.out", "w", stdout); int n, m, size, block; scanf("%d", &n); for(int i = 0; i < n; i++) scanf("%d", &A[i]); scanf("%d", &m); for(int i = 1; i <= m; i++) { int k, x, b; scanf("%d %d", &k, &x); b = x/size; if(k == 1) { int ans = 0; while(x < n) ans++, x += A[x]; printf("%d\n", ans); } else { scanf("%d", &A[x]); } } return 0; }