bzoj2002: [Hnoi2010]Bounce 弹飞绵羊 [分块][LCT]
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
1 2 1 1
3
1 1
2 1 1
1 1
Sample Output
2
3
3
直接模拟肯定超时
考虑分块优化
(其实是不会lct辣!)
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<cmath> 5 using namespace std; 6 7 inline int read(){ 8 char ch; 9 int re=0; 10 bool flag=0; 11 while((ch=getchar())!='-'&&(ch<'0'||ch>'9')); 12 ch=='-'?flag=1:re=ch-'0'; 13 while((ch=getchar())>='0'&&ch<='9') re=re*10+ch-'0'; 14 return flag?-re:re; 15 } 16 17 const int maxn=200001; 18 19 int n,m; 20 //b[][1]跳到下一分块中的位置 21 //b[][0]跳到下一分块需要的步数 22 //c[]分块序号 23 int a[maxn],b[maxn][2],c[maxn]; 24 25 int main(){ 26 //freopen("temp.in","r",stdin); 27 n=read(); 28 for(int i=0;i<n;i++) a[i]=read(); 29 for(int i=0,v=1,h=(int)sqrt(n);i<n;i++){ 30 c[i]=v; 31 if((i+1)%h==0) v++; 32 } 33 for(int i=n-1;i>=0;i--){ 34 //跳出分块或弹飞 35 if(i+a[i]>n-1||c[i+a[i]]!=c[i]) b[i][1]=i+a[i]; 36 else b[i][1]=b[i+a[i]][1]; 37 //记录多少步跳出分块 38 if(c[i+a[i]]!=c[i]) b[i][0]=1; 39 else b[i][0]=b[i+a[i]][0]+1; 40 } 41 m=read(); 42 int opt,pos,num,ans; 43 while(m--){ 44 opt=read(); 45 if(opt==1){ 46 pos=read(); 47 ans=0; 48 while(pos<=n-1){ 49 ans+=b[pos][0]; 50 pos=b[pos][1]; 51 } 52 if(ans==0) puts("1"); 53 else printf("%d\n",ans); 54 } 55 else{ 56 pos=read(); num=read(); 57 a[pos]=num; 58 if(pos+num>n-1||c[pos+num]!=c[pos]) b[pos][1]=pos+num; 59 else b[pos][1]=b[pos+num][1]; 60 if(c[pos+num]!=c[pos]) b[pos][0]=1; 61 else b[pos][0]=b[pos+num][0]+1; 62 for(int i=pos-1;i>=0;i--){ 63 if(c[i]!=c[pos]) break; 64 if(i+a[i]<=n-1&&c[i+a[i]]==c[i]) b[i][1]=b[i+a[i]][1]; 65 if(c[i+a[i]]==c[i]) b[i][0]=b[i+a[i]][0]+1; 66 } 67 } 68 } 69 return 0; 70 }