[HNOI2010]彈飛綿羊(分塊)
阿新 • • 發佈:2018-03-18
存在 name reg ring include size div string etc
題目描述
某天,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。
輸出格式:對於每個i=1的情況,你都要輸出一個需要的步數,占一行。
輸入輸出樣例
輸入樣例#1: 復制4 1 2 1 1 3 1 1 2 1 1 1 1輸出樣例#1: 復制
2 3
說明
對於20%的數據n,m<=10000,對於100%的數據n<=200000,m<=100000
題解
這裏需要我們處理出每一塊中,進入某個點後,會進入下一個塊的哪一個點,需要幾次才能彈出塊,修改時記得同時修改相應塊的內容。
靠大佬自己思維了。
#include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<iostream> using namespace std; const int N=500001; int n,m,ch[N],tmp,belong[N],l[N],r[N],num,out[N],sum[N]; int read() { int x=0,w=1;char ch=getchar();while(ch>‘9‘||ch<‘0‘){if(ch==‘-‘)w=-1;ch=getchar();} while(ch>=‘0‘&&ch<=‘9‘)x=x*10+ch-‘0‘,ch=getchar(); return w*x; } void build() { num=tmp;if(tmp*tmp<n)num++; for(int i=1;i<=num;i++) { l[i]=num*(i-1)+1;r[i]=num*i; } r[num]=n; int s=1 ; for (int i=1;i<=n;i++) {if (i>r[s]) s++; belong[i]=s;} } void change(int left,int right) { for(int i=right;i>=left;i--) { if(i+ch[i]>r[belong[i]])sum[i]=1,out[i]=i+ch[i]; else sum[i]=sum[i+ch[i]]+1,out[i]=out[i+ch[i]]; } } int main() { n=read();tmp=sqrt(n); for(int i=1;i<=n;i++) { ch[i]=read(); } build(); change(1,n); m=read(); for(int i=1;i<=m;i++) { int qwq; qwq=read(); if(qwq==1) { int x;x=read();x++; int ans=sum[x],qwq=out[x]; for(int i=belong[x];i<=tmp&&qwq<=n;i++) ans+=sum[qwq],qwq=out[qwq]; printf("%d\n",ans); } else { int x,y;x=read();x++;y=read();ch[x]=y; change(l[belong[x]],r[belong[x]]); } } return 0; }
[HNOI2010]彈飛綿羊(分塊)