BZOJ 2002:Bounce 彈飛綿羊(分塊)
阿新 • • 發佈:2018-12-15
2002: [Hnoi2010]Bounce 彈飛綿羊
Time Limit: 10 Sec Memory Limit: 259 MB Submit: 14944 Solved: 7598 [Submit][Status][Discuss]
Description
某天,Lostmonkey發明了一種超級彈力裝置,為了在他的綿羊朋友面前顯擺,他邀請小綿羊一起玩個遊戲。遊戲一開始,Lostmonkey在地上沿著一條直線擺上n個裝置,每個裝置設定初始彈力系數ki,當綿羊達到第i個裝置時,它會往後彈ki步,達到第i+ki個裝置,若不存在第i+ki個裝置,則綿羊被彈飛。綿羊想知道當它從第i個裝置起步時,被彈幾次後會被彈飛。為了使得遊戲更有趣,Lostmonkey可以修改某個彈力裝置的彈力系數,任何時候彈力系數均為正整數。
Input
第一行包含一個整數n,表示地上有n個裝置,裝置的編號從0到n-1,接下來一行有n個正整數,依次為那n個裝置的初始彈力系數。第三行有一個正整數m,接下來m行每行至少有兩個數i、j,若i=1,你要輸出從j出發被彈幾次後被彈飛,若i=2則還會再輸入一個正整數k,表示第j個彈力裝置的係數被修改成k。對於20%的資料n,m<=10000,對於100%的資料n<=200000,m<=100000
Output
對於每個i=1的情況,你都要輸出一個需要的步數,佔一行。
Sample Input
4 1 2 1 1 3 1 1 2 1 1 1 1
Sample Output
2 3
思路
將n個彈力系統進行分塊,分塊的長度為
在進行更新的時候只需對更新位置所在的分塊進行更新就可以了
修改和查詢的複雜度都是,第一次讀入完成更新的時候複雜度為
AC程式碼
/* * @Author: WZY * @School: HPU * @Date: 2018-10-13 17:08:28 * @Last Modified by: WZY * @Last Modified time: 2018-10-13 17:35:39 */ #include <stdio.h> #include <string.h> #include <iostream> #include <algorithm> #include <math.h> #include <limits.h> #include <map> #include <stack> #include <queue> #include <vector> #include <set> #include <string> #include <time.h> #define ll long long #define ull unsigned long long #define ms(a,b) memset(a,b,sizeof(a)) #define pi acos(-1.0) #define INF 0x7f7f7f7f #define lson o<<1 #define rson o<<1|1 #define bug cout<<"---------"<<endl #define debug(...) cerr<<"["<<#__VA_ARGS__":"<<(__VA_ARGS__)<<"]"<<"\n" const double E=exp(1); const int maxn=1e6+10; const int mod=1e9+7; using namespace std; int n,m,block; int a[maxn]; int step[maxn];//記錄到當前位置跳了多少次 int Next[maxn];//記錄下一個位置 inline void update(int i) { // pos記錄當前的位置 int pos=i+a[i]; // 如果跳了出去 if(pos>=n) { step[i]=1; Next[i]=-1; } // 如果跳出當前分塊 else if(pos>=(i/block+1)*block) { step[i]=1; Next[i]=pos; } // 還在當前分塊 else { step[i]=step[pos]+1; Next[i]=Next[pos]; } } int main(int argc, char const *argv[]) { ios::sync_with_stdio(false); #ifndef ONLINE_JUDGE freopen("in.txt", "r", stdin); freopen("out.txt", "w", stdout); double _begin_time = clock(); #endif cin>>n; block=sqrt(n); for(int i=0;i<n;i++) cin>>a[i]; // 從後往前更新 for(int i=n-1;~i;i--) update(i); cin>>m; while(m--) { int x,y,z; cin>>x; if(x==1) { int ans=0; cin>>y; for(int i=y;i!=-1;i=Next[i]) ans+=step[i]; cout<<ans<<endl; } else { cin>>y>>z; // 更新a[y]的值 a[y]=z; // 只更新y所在分塊的資料 for(int i=y;i>=(y/block)*block;i--) update(i); } } #ifndef ONLINE_JUDGE double _end_time = clock(); printf("time = %lf ms.", _end_time - _begin_time); #endif return 0; }