洛谷P3203彈飛綿羊
阿新 • • 發佈:2018-10-31
+= %d 分塊 printf 神奇 lse init str ios
傳送門啦
非常神奇的分塊大法。
每塊分 √N 個元素 , 預處理出來:對於每個點,記錄兩個量:一個是它要彈幾次才能出它所在的這個塊,另外一個是它彈出這個塊後到哪個點。
查詢操作:一塊一塊跳過去 單次復雜度 O(√N)
修改操作:只需要把相應的塊改一遍就好了 這個也是O(√N)
#include <iostream> #include <cstring> #include <cstdio> #include <algorithm> #include <cmath> using namespace std; const int maxn = 200005; const int maxm = 100005; inline int read(){ char ch = getchar(); int f = 1 , x = 0; while(ch > '9' || ch < '0'){if(ch == '-')f = -1;ch =getchar();} while(ch >= '0' && ch <= '9'){x = (x << 1) + (x << 3) + ch - '0';ch = getchar();} return x * f; } int n,a[maxn],m,flag,x,y,ans; int l[maxn],r[maxn],cnt,belong[maxn],to[maxn],step[maxn]; void init(){ int t = sqrt(n); if(n / t) cnt = n / t + 1; else cnt = n / t; for(int i=1;i<=cnt;i++){ l[i] = r[i-1] + 1; r[i] = min(l[i] + t - 1 , n); } int x = 1; for(int j=1;j<=n;j++){ belong[j] = x; if(j == r[x] && x <= cnt) x++; } for(int i=n;i>=1;i--){ to[i] = i + a[i]; if(to[i] > r[belong[i]]) step[i] = 1; else { step[i] = step[to[i]] + 1; to[i] = to[to[i]]; } } } int main(){ n = read(); for(int i=1;i<=n;i++) a[i] = read(); init(); m = read(); while(m--){ ans = 0; flag = read(); if(flag == 1){ x = read(); x++; while(x <= n){ ans += step[x]; x = to[x]; } printf("%d\n",ans); } else { x = read(); y = read(); x++; a[x] = y; for(int i=r[belong[x]];i>=l[belong[x]];i--){ to[i] = i + a[i]; if(to[i] > r[belong[i]]) step[i] = 1; else { step[i] = step[to[i]] + 1; to[i] = to[to[i]]; } } } } return 0; }
洛谷P3203彈飛綿羊