【分块】【LCT】bzoj2002 [Hnoi2010]Bounce 弹飞绵羊

分块,每个点统计还有几步弹出该块,以及它弹出块后的下一个节点是哪个点。

注意:update某个点的时候,会可能对当前块内 该点及以前的点 产生影响,所以对这部分点进行更新。

 1 #include<cstdio>
 2 #include<cmath>
 3 using namespace std;
 4 int n,m,op,x,y,sz,a[200001],l[450],sum,num[200001],b[200001],c[200001];
 5 bool vis[200001];
 6 void makeblock()
 7 {
 8     int r;sz=sqrt(n);
 9     for(sum=1;sum*sz<n;sum++)
10       {
11         l[sum]=(sum-1)*sz;
12         r=sum*sz-1;
13           for(int i=l[sum];i<=r;i++)
14           num[i]=sum;
15       }
16     l[sum]=sz*(sum-1);
17     r=n-1;
18     for(int i=l[sum];i<=r;i++)
19       num[i]=sum;
20 }
21 void init()
22 {
23     for(int i=0;i<n;i++)
24       {
25         int u=i,cnt=0;
26         while(num[u]==num[i]){u+=a[u];cnt++;}
27         b[i]=cnt;c[i]=u;
28       }
29 }
30 inline int query(int u)
31 {
32     int res=0;
33     while(u<n){res+=b[u];u=c[u];}
34     return res;
35 }
36 inline void update(const int &p,const int &val)
37 {
38     a[p]=val;
39     if(num[p+a[p]]!=num[p]){b[p]=1;c[p]=p+a[p];}
40     else{b[p]=b[p+a[p]]+1;c[p]=c[p+a[p]];}
41     for(int i=p;i>=l[num[p]];i--)
42       if(i+a[i]<=p){b[i]=b[i+a[i]]+1;c[i]=c[i+a[i]];}
43 }
44 int Res,Num;char C,CH[20];
45 inline int G()
46 {
47     Res=0;C='*'; 
48     while(C<'0'||C>'9')C=getchar();
49     while(C>='0'&&C<='9'){Res=Res*10+(C-'0');C=getchar();}
50     return Res;
51 }
52 inline void P(int x)
53 {
54     Num=0;  
55     while(x>0)CH[++Num]=x%10,x/=10;
56     while(Num)putchar(CH[Num--]+48);
57     putchar('\n');
58 }
59 int main()
60 {
61     n=G();for(int i=0;i<n;i++)a[i]=G();
62     makeblock();init();m=G();
63     for(int i=1;i<=m;i++)
64       {
65           op=G();
66           if(op==1){x=G();P(query(x));}
67           else{x=G();y=G();update(x,y);}
68       }
69     return 0;
70 }

 

posted @ 2014-09-10 18:25  AutSky_JadeK  阅读(154)  评论(0编辑  收藏
TVアニメ「Charlotte(シャーロット)」公式サイト TVアニメ「Charlotte(シャーロット)」公式サイト