1. 程式人生 > >洛谷 P3203 [HNOI2010]彈飛綿羊 分塊

洛谷 P3203 [HNOI2010]彈飛綿羊 分塊

我們只需將序列分成 n \sqrt{n} 塊,對於每一個點維護一個 v a l [

i ] val[i] t o [ i ] to[i]
,分別代表該點跳到下一個塊所需要的代價以及會跳到的節點編號。在查詢時,我們最多會跳 n \sqrt{n} 塊,修改的時候將節點所在區間暴力修改即可。
Code:

#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std; const int maxn = 2000000 + 3; int arr[maxn], n, block, to[maxn], val[maxn], m, belong[maxn]; struct Data_Structure{ inline void init(){ block = sqrt(n); for(int i = n;i >= 1; --i) { belong[i] = (i - 1) / block + 1; to[i] = belong[i + arr[i]] == belong[i] ? to[i + arr[i]] : i + arr[i]; val[i] = belong[i + arr[i]] == belong[i] ? val[i + arr[i]] + 1 : 1; } } inline int solve(){ int pos, ans = 0; scanf("%d",&pos); ++pos; while(pos <= n){ ans += val[pos]; pos = to[pos]; } return ans; } inline void update(){ int pos, data; scanf("%d%d",&pos,&data); ++pos; arr[pos] = data; for(int i = min(belong[pos] * block, n); i >= (belong[pos] - 1) * block + 1; --i) { to[i] = belong[i + arr[i]] == belong[i] ? to[i + arr[i]] : i + arr[i]; val[i] = belong[i + arr[i]] == belong[i] ? val[i + arr[i]] + 1 : 1; } } }T; int main(){ scanf("%d",&n); for(int i = 1;i <= n; ++i) scanf("%d",&arr[i]); T.init(); scanf("%d",&m); while(m--) { int opt; scanf("%d",&opt); switch(opt) { case 1: { printf("%d\n", T.solve()); break; } case 2: { T.update(); break; } } } return 0; }