BZOJ2002 [HNOI2010]彈飛綿羊
阿新 • • 發佈:2018-11-18
return 需要 題目 fprintf fir 下標 span com 一個
題目藍鏈
Description
有\(n\)個彈簧排成一列,每一個彈簧都會給定一個向後彈射的距離,然後需要支持兩個操作
查詢從某個彈簧開始需要彈多少次後,就會彈到第\(n\)個彈簧之後
修改某個彈簧的向後彈射距離
Solution
考慮分塊,每一個塊中維護每一個位置要跳多少次才能跳出這個塊,跳出去後是落在那個位置
查詢直接\(\mathcal{O}(\sqrt n)\)一個塊一個塊的模擬去跳,修改就更新修改位置所在塊的信息就可以了
Code
#include <bits/stdc++.h> using namespace std; #define fst first #define snd second #define squ(x) ((LL)(x) * (x)) #define debug(...) fprintf(stderr, __VA_ARGS__) typedef long long LL; typedef pair<int, int> pii; inline int read() { int sum = 0, fg = 1; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == ‘-‘) fg = -1; for (; isdigit(c); c = getchar()) sum = (sum << 3) + (sum << 1) + (c ^ 0x30); return fg * sum; } const int maxn = 2e5 + 10; const int B = 400; int n, m, blks, f[maxn], S[maxn], T[maxn]; int pos(int x) { return x <= n ? (x - 1) / B + 1 : blks + 1; } int main() { freopen("sheep.in", "r", stdin); freopen("sheep.out", "w", stdout); n = read(); for (int i = 1; i <= n; i++) f[i] = read() + i; blks = (n - 1) / B + 1; for (int i = 1; i <= blks; i++) { int e = min(i * B, n), tmp = (i - 1) * B; for (int j = e; j > tmp; j--) if (f[j] <= e) S[j] = S[f[j]] + 1, T[j] = T[f[j]]; else S[j] = 1, T[j] = f[j]; } m = read(); while (m--) { int op = read(); if (op == 1) { int x = read() + 1, ans = 0; while (pos(x) <= blks) ans += S[x], x = T[x]; printf("%d\n", ans); } if (op == 2) { int x = read() + 1, p = pos(x); f[x] = read() + x; int tmp = (p - 1) * B, e = min(p * B, n); for (int i = x; i > tmp; i--) { if (f[i] <= e) S[i] = S[f[i]] + 1, T[i] = T[f[i]]; else S[i] = 1, T[i] = f[i]; } } } return 0; }
Summary
這道題代碼細節是真的多,我打之前沒有想清一些的細節。所以我一邊打一邊想,調了我一個小時
一定要註意區分數組的下標和實際位置
BZOJ2002 [HNOI2010]彈飛綿羊