[BZOJ 2002][Hnoi 2010]Bounce 弹飞绵羊

有两种写法

一.可以用块状链表水过

代码:

 1 #include<cmath>
 2 #include<cstdio>
 3 #define N 200100
 4 using namespace std;
 5 
 6 int n,m,q,cnt,a,b,c;
 7 int s[N],f[N],g[N],num[N];
 8 
 9 void build()
10 {
11     m=(int) sqrt(n);
12     cnt=(n-1)/m;
13     for (int i=0;i<n;i++) num[i]=i/m;
14     num[n]=cnt+1;
15     for (int i=n-1;i>=0;i--)
16     {
17         if (s[i]+i>=n){f[i]=1;g[i]=n;}
18         else if (num[i]==num[s[i]+i]) {f[i]=f[s[i]+i]+1;g[i]=g[s[i]+i];}
19         else {f[i]=1;g[i]=s[i]+i;}
20     }
21 }
22 
23 void Query(int a)
24 {
25     int ans=0;
26     while (num[a]<=cnt)
27     {
28         ans+=f[a];
29         a=g[a];
30     }
31     printf("%d\n",ans);
32 }
33 
34 void Change(int a,int b)
35 {
36     s[a]=b;
37     for (int i=a;i>=0&&num[i]==num[a];i--)
38     {
39         if (s[i]+i>=n){f[i]=1;g[i]=n;}
40         else if (num[i]==num[s[i]+i]) {f[i]=f[s[i]+i]+1;g[i]=g[s[i]+i];}
41         else {f[i]=1;g[i]=s[i]+i;}
42     }
43 }
44 
45 int main()
46 {
47     scanf("%d",&n);
48     for (int i=0;i<n;i++) scanf("%d",s+i);
49     build();
50     scanf("%d",&q);
51     for (int i=1;i<=q;i++)
52     {
53         scanf("%d%d",&a,&b);
54         if (a==1) Query(b);
55         else {scanf("%d",&c);Change(b,c);}
56     }
57     return 0;
58 }

二.lct可以完美解决,这个题算是lct模板题吧

 1 #include<cstdio>
 2 #define N 200100
 3 
 4 int n,m,a,b,c,null;
 5 int f[N],pos[N],son[N][2],sum[N];
 6 
 7 void Change(int a,int b,int c)
 8 {
 9     if (b) f[b]=a;
10     if (b) pos[b]=c;
11     if (c<2) son[a][c]=b;
12 }
13 
14 void update(int x){sum[x]=sum[son[x][0]]+sum[son[x][1]]+1;}
15 
16 void ziag(int x)
17 {
18     int y=f[x],P=pos[x],S=son[x][P^1];
19     Change(f[y],x,pos[y]);
20     Change(y,S,P);
21     Change(x,y,P^1);
22     update(y);
23     update(x);
24 }
25 
26 void Splay(int x)
27 {
28     int y,t1,t2;
29     while (1)
30     {
31         y=f[x];
32         if (pos[x]==2) return;
33         t1=pos[x];
34         ziag(x);
35         if (pos[x]==2) return;
36         t2=pos[x];
37         ziag(x);
38         if (t1==t2) ziag(y);
39     }
40 }
41 
42 void Access(int v)
43 {
44     int u=v;
45     v=0;
46     while (u)
47     {
48         Splay(u);
49         pos[son[u][1]]=2;
50         son[u][1]=v;
51         update(u);
52         if (v){f[v]=u;pos[v]=1;}
53         v=u;
54         u=f[u];
55     }
56 }
57 
58 void Cut(int v)
59 {
60     Splay(v);
61     f[son[v][0]]=f[v];
62     pos[son[v][0]]=2;
63     son[v][0]=0;
64     update(v);
65 }
66 
67 int main()
68 {
69     scanf("%d",&n);
70     pos[0]=2;
71     for (int i=1;i<=n;i++)
72     {
73         scanf("%d",&a);
74         if (i+a<=n) f[i]=i+a;
75         else f[i]=0;
76         pos[i]=2;
77         sum[i]=1;
78     }
79     scanf("%d",&m);
80     for (int i=0;i<m;i++)
81     {
82         scanf("%d%d",&a,&b);
83         b++;
84         if (a==1)
85         {
86             Access(b);
87             Splay(b);
88             printf("%d\n",sum[b]);
89         }
90         else
91         {
92             scanf("%d",&c);
93             Cut(b);
94             if (b+c<=n) f[b]=b+c;
95             else f[b]=0;
96         }
97     }
98     return 0;
99 }

 

posted @ 2015-01-21 15:20  Rebel_ice  阅读(88)  评论(0编辑  收藏