1. 程式人生 > >[HNOI2010]BOUNCE 彈飛綿羊

[HNOI2010]BOUNCE 彈飛綿羊

eset pan cor 接下來 重建 一行 開始 sqrt 出發

題目描述

某天,Lostmonkey發明了一種超級彈力裝置,為了在他的綿羊朋友面前顯擺,他邀請小綿羊一起玩個遊戲。遊戲一開始,Lostmonkey在地上沿著一條直線擺上n個裝置,每個裝置設定初始彈力系數ki,當綿羊達到第i個裝置時,它會往後彈ki步,達到第i+ki個裝置,若不存在第i+ki個裝置,則綿羊被彈飛。綿羊想知道當它從第i個裝置起步時,被彈幾次後會被彈飛。為了使得遊戲更有趣,Lostmonkey可以修改某個彈力裝置的彈力系數,任何時候彈力系數均為正整數。

輸入輸出格式

輸入格式:

第一行包含一個整數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

輸出格式:

對於每個i=1的情況,你都要輸出一個需要的步數,占一行。

輸入輸出樣例

輸入樣例#1:
4
1 2 1 1
3
1 1
2 1 1
1 1
輸出樣例#1:
2
3

解題思路

分塊經典例題,把這個長度為n的序列分成√n個,對於每段小區間,我們維護以下這幾個值:

s[i]---從第i個點跳出該小區間需要的步數(step)

t[i]---跳出該小區間後會到達哪個節點(to)

查詢時每次直接 step+=s[i],i=[i],復雜度不超過√n;

修改時直接賦值後把當前塊暴力重建,復雜度為√n;

總時間復雜度O(m*√n)

總空間復雜度O(n)

分點信息(鼠標移到方塊上有詳細信息)

#1 AC 5ms/14937kB #2 AC 284ms/14937kB #3 AC 5ms/14937kB #4 AC 265ms/14937kB #5 AC 188ms/14937kB #6 AC 274ms/14937kB #7 AC 158ms/14937kB #8 AC 292ms/14937kB #9 AC 441ms/14937kB #10AC448ms/14937kB

源代碼

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cmath>
 4 #include <algorithm>
 5
#define LL long long 6 using namespace std; 7 const int N=200200; 8 int k[N],bl[N],t[N],s[N]; 9 int blo,n,m,tot; 10 int read(){ 11 int v=0,f=1;char c=getchar(); 12 while(c>9||c<0){if(c==-)f*=-1;c=getchar();} 13 while(c<=9&&c>=0)v=v*10+c-0,c=getchar(); 14 return v*f; 15 } 16 void reset(int x){ 17 for(int i=min(n,x*blo);i>=(x-1)*blo+1;i--){ 18 int to=i+k[i]; 19 if(to>min(n,x*blo))s[i]=1,t[i]=to; 20 else { 21 s[i]=s[to]+1; 22 t[i]=t[to]; 23 } 24 } 25 } 26 int query(int x){ 27 int rtn=0; 28 while(x<=n){ 29 rtn+=s[x]; 30 x=t[x]; 31 } 32 return rtn; 33 } 34 void change(int x,int v){ 35 k[x]=v; 36 reset(bl[x]); 37 } 38 int main(){ 39 n=read();blo=sqrt(n); 40 for(int i=1;i<=n;i++){ 41 k[i]=read(); 42 bl[i]=(i-1)/blo+1; 43 } 44 tot=bl[n]; 45 for(int i=1;i<=tot;i++)reset(i); 46 m=read(); 47 while(m--){ 48 int opt,p,v; 49 opt=read(); 50 if(opt==1){ 51 p=read(); 52 printf("%d\n",query(p+1)); 53 } 54 if(opt==2){ 55 p=read();v=read(); 56 change(p+1,v); 57 } 58 } 59 return 0; 60 }

[HNOI2010]BOUNCE 彈飛綿羊