[BZOJ 2002][Hnoi2010]Bounce 弹飞绵羊(分块)
Description
某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏。游戏一开始,Lostmonkey在地上沿着一条直线摆上n个装置,每个装置设定初始弹力系数ki,当绵羊达到第i个装置时,它会往后弹ki步,达到第i+ki个装置,若不存在第i+ki个装置,则绵羊被弹飞。绵羊想知道当它从第i个装置起步时,被弹几次后会被弹飞。为了使得游戏更有趣,Lostmonkey可以修改某个弹力装置的弹力系数,任何时候弹力系数均为正整数。
Solution
分块大法好…迷之优雅的暴力
维护每个点跳到下一个块的位置和所需要的次数 修改和查询应该都是sqrt(n)吧
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #define MAXN 200002 using namespace std; int n,m,init,k[MAXN],bump[MAXN],cnt[MAXN]; int main() { scanf("%d",&n); init=(int)sqrt(n+0.1); for(int i=0;i<n;i++) { scanf("%d",&k[i]); bump[i]=i+k[i]; cnt[i]=1; } for(int i=n-1;i>=0;i--) { int t; while(bump[i]<min((i/init+1)*init,n)) { t=bump[i]; bump[i]=bump[t]; cnt[i]+=cnt[t]; } } scanf("%d",&m); for(int i=1;i<=m;i++) { int x,y,ans,t; scanf("%d%d",&x,&y); if(x==1) { ans=0,t=y; while(t<n) { ans+=cnt[t]; t=bump[t]; } printf("%d\n",ans); } else { scanf("%d",&k[y]); int s=y/init*init; for(int j=y;j>=s;j--) { bump[j]=j+k[j]; cnt[j]=1; while(bump[j]<min((j/init+1)*init,n)) { t=bump[j]; bump[j]=bump[t]; cnt[j]+=cnt[t]; } } } } return 0; }