数据结构练习

1、http://www.wikioi.com/problem/1036/

用的是树链剖分写的LCA

 1 #include<cstring>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<vector>
 5 using namespace std;
 6 const int maxn=30000;
 7 struct xyz111
 8 {
 9     int tid,size,father,son,top,dep;
10 }tree[maxn+50];
11 vector<int> g[maxn+50];
12 int n,m,label=0,q[maxn+50];
13 void dfs(int k,int father,int dep)
14 {
15     tree[k]={0,1,father,0,0,dep};
16     int maxsize=0;
17     for(int i=0;i<g[k].size();++i)
18         if(g[k][i]!=father)
19         {
20             dfs(g[k][i],k,dep+1);
21             tree[k].size+=tree[g[k][i]].size;
22             if(tree[g[k][i]].size>maxsize) maxsize=tree[g[k][i]].size,tree[k].son=g[k][i];
23         }
24 }
25 void connect(int k,int top)
26 {
27     tree[k].tid=++label;
28     tree[k].top=top;
29     if(tree[k].son!=0) connect(tree[k].son,top);
30     for(int i=0;i<g[k].size();++i)
31         if(tree[k].father!=g[k][i]&&tree[k].son!=g[k][i]) connect(g[k][i],g[k][i]);
32 }
33 int question(int x,int y)
34 {
35     int a=x,b=y;
36     while(tree[x].top!=tree[y].top)
37     {
38         if(tree[tree[x].top].dep<tree[tree[y].top].dep) swap(x,y);
39         x=tree[tree[x].top].father;
40     }
41     if(tree[x].dep>tree[y].dep) swap(x,y);
42     return tree[a].dep+tree[b].dep-2*tree[x].dep; 
43 }
44 int main()
45 {
46     scanf("%d",&n);
47     for(int i=1;i<=n;++i) g[i].clear();
48     for(int i=1;i<n;++i)
49     {
50         int x,y;
51         scanf("%d %d",&x,&y);
52         g[x].push_back(y);
53         g[y].push_back(x);
54     }
55     scanf("%d",&m);
56     for(int i=1;i<=m;++i) scanf("%d",&q[i]); 
57     dfs(1,0,0);
58     connect(1,1);
59     int ans=0;
60     for(int i=2;i<=m;++i) ans+=question(q[i-1],q[i]);
61     printf("%d",ans);
62     return 0;
63 }
View Code

2、http://www.wikioi.com/problem/1082/

线段树的Lazy,好久没写线段树,没注意到我的存储方法线段树存储不是满的导致判断溢出的时候BUG了……

 1 #include<cstring>
 2 #include<algorithm>
 3 #include<cstdio>
 4 using namespace std;
 5 const long long maxn=200000;
 6 struct xyz111
 7 {
 8     long long l,r,add,sum;
 9 }tree[4*maxn];
10 long long n,q,a[maxn+50];
11 void push_down(long long k)
12 {
13     tree[k*2].add+=tree[k].add,tree[k*2+1].add+=tree[k].add;
14     tree[k*2].sum+=(tree[k*2].r-tree[k*2].l+1)*tree[k].add,tree[k*2+1].sum+=(tree[k*2+1].r-tree[k*2+1].l+1)*tree[k].add;
15     tree[k].add=0;
16 }
17 void build(long long k,long long l,long long r)
18 {
19     tree[k]={l,r,0,0};
20     if(l==r) return;
21     long long mid=(l+r)/2;
22     build(k*2,l,mid);
23     build(k*2+1,mid+1,r);
24 }
25 void add(long long k,long long l,long long r,long long x)
26 {
27     if((tree[k].l==0&&tree[k].r==0)||tree[k].l>r||tree[k].r<l) return;
28     if(tree[k].l>=l&&tree[k].r<=r) 
29     {
30         tree[k].add+=x;
31         tree[k].sum+=(tree[k].r-tree[k].l+1)*x;
32         return;
33     }
34     push_down(k);
35     add(k*2,l,r,x);
36     add(k*2+1,l,r,x);
37     tree[k].sum=tree[k*2].sum+tree[k*2+1].sum;
38 }
39 long long ask(long long k,long long l,long long r)
40 {
41     if((tree[k].l==0&&tree[k].r==0)||tree[k].l>r||tree[k].r<l) return 0;
42     if(tree[k].l>=l&&tree[k].r<=r) return tree[k].sum;
43     push_down(k);
44     return ask(k*2,l,r)+ask(k*2+1,l,r);
45 }
46 int main()
47 {
48     scanf("%d",&n);
49     for(int i=1;i<=4*n;++i) tree[i]={0,0,0,0};
50     build(1,1,n);
51     for(int i=1;i<=n;++i) scanf("%lld",&a[i]);
52     for(int i=1;i<=n;++i) add(1,i,i,a[i]);
53     scanf("%d",&q);
54     for(int i=1;i<=q;++i)
55     {
56         long long l,x,y,z;
57         scanf("%lld",&l);
58         if(l==1)
59         {
60             scanf("%lld %lld %lld",&x,&y,&z);
61             add(1,x,y,z);
62         }
63         else 
64         {
65             scanf("%lld %lld",&x,&y);
66             printf("%lld\n",ask(1,x,y));
67         }
68     }
69     return 0;
70 }
View Code

3、http://www.wikioi.com/problem/1191/

简单的线段树lazy

 1 #include<cstring>
 2 #include<algorithm>
 3 #include<cstdio>
 4 using namespace std;
 5 const int maxn=200000;
 6 struct xyz111
 7 {
 8     int l,r,v,sum;
 9 }tree[maxn*4];
10 int n,m;
11 void build(int k,int l,int r)
12 {
13     tree[k]={l,r,0,0};
14     if(l==r) return;
15     int mid=(l+r)/2;
16     build(k*2,l,mid);
17     build(k*2+1,mid+1,r);
18 }
19 void push_down(int k)
20 {
21     if(tree[k].v==0) return;
22     tree[k*2].v=1,tree[k*2].sum=tree[k*2].r-tree[k*2].l+1;
23     tree[k*2+1].v=1,tree[k*2+1].sum=tree[k*2+1].r-tree[k*2+1].l+1;
24     tree[k].v=0;
25 }
26 void update(int k,int l,int r)
27 {
28     if((tree[k].l==0&&tree[k].r==0)||tree[k].l>r||tree[k].r<l) return;
29     if(tree[k].l>=l&&tree[k].r<=r) 
30     {
31         tree[k].sum=tree[k].r-tree[k].l+1;
32         tree[k].v=1;
33         return;
34     }
35     push_down(k);
36     update(k*2,l,r);
37     update(k*2+1,l,r);
38     tree[k].sum=tree[k*2].sum+tree[k*2+1].sum;
39 }
40 int ask(int k,int l,int r)
41 {
42     if((tree[k].l==0&&tree[k].r==0)||tree[k].l>r||tree[k].r<l) return 0;
43     if(tree[k].l>=l&&tree[k].r<=r) return tree[k].sum;
44     push_down(k);
45     return ask(k*2,l,r)+ask(k*2+1,l,r);
46 }
47 int main()
48 {
49     scanf("%d %d",&n,&m);
50     for(int i=1;i<=4*n;++i) tree[i]={0,0,0};
51     build(1,1,n);
52     for(int i=1;i<=m;++i)
53     {
54         int x,y;
55         scanf("%d %d",&x,&y);
56         update(1,x,y);
57         printf("%d\n",n-ask(1,1,n));
58     }
59     return 0;
60 }
View Code

4、http://www.wikioi.com/problem/1299/ 

上一题的加强版,数据范围变大了,卡线段树,正解是并查集,在模拟的基础上,将每个点的祖先定为右边的最近的没被染色的点,所以每次染色一个区间就可以很快了

 1 #include<cstring>
 2 #include<algorithm>
 3 #include<cstdio>
 4 using namespace std;
 5 const int maxn=2000000;
 6 int f[maxn+50],n,m;
 7 long long find(long long x)
 8 {
 9     if(f[x]==x) return x;
10     return f[x]=find(f[x]);
11 }
12 int main()
13 {
14     scanf("%d %d",&n,&m);
15     for(int i=1;i<=n;++i) f[i]=i;
16     int ans=n;
17     for(int i=1;i<=m;++i)
18     {
19         int x,y;
20         scanf("%d %d",&x,&y);
21         x=find(x);
22         while(x<=y)
23         {
24             --ans;
25             f[x]=x+1;
26             x=find(x);
27         }
28         printf("%d\n",ans);
29     }
30     return 0;
31 }
View Code

 5、http://www.wikioi.com/problem/1286/ 

经典的平衡树题,这个是用Treap写的

  1 #include<cstring>
  2 #include<cstdio>
  3 #include<algorithm>
  4 #include<ctime>
  5 using namespace std;
  6 const int maxn=100000,inf=1e9;
  7 struct xyz111
  8 {
  9     xyz111* ch[2];
 10     int size,value,key,num;
 11     int cmp(int x)
 12     {
 13         if(x==value) return -1;
 14         return value<x;
 15     }
 16     void maintain()
 17     {
 18         size=num;
 19         if(ch[0]!=NULL) size+=ch[0]->size;
 20         if(ch[1]!=NULL) size+=ch[1]->size;
 21     }
 22 };
 23 xyz111* root=NULL;
 24 int n,m,s=0;
 25 void rorate(xyz111* &o,int d)
 26 {
 27     xyz111* k=o->ch[d^1];
 28     o->ch[d^1]=k->ch[d];
 29     k->ch[d]=o;
 30     o->maintain();
 31     k->maintain();
 32     o=k;
 33 }
 34 void insert(xyz111* &o,int x)
 35 {
 36     if(o==NULL)
 37     {
 38         o=new xyz111();
 39         o->ch[0]=o->ch[1]=NULL;
 40         o->size=1;
 41         o->value=x;
 42         o->key=rand()%inf;
 43         o->num=1;
 44     }
 45     else
 46     {
 47         int d=o->cmp(x);
 48         if(d==-1) ++o->num;
 49         else
 50         {
 51             insert(o->ch[d],x);
 52             if(o->ch[d]->key>o->key) rorate(o,d^1);
 53         }
 54     }
 55     o->maintain();
 56 }
 57 void dfs(xyz111* &o,int x)
 58 {
 59     if(o==NULL) return;
 60     int d=o->cmp(x);
 61     if(d==0||d==-1) dfs(o->ch[0],x);
 62     if(d==1)
 63     {
 64         if(o->ch[1]!=NULL) o=o->ch[1];else o=NULL;
 65         dfs(o,x);
 66     }
 67     if(o!=NULL)o->maintain(); 
 68 }
 69 int kth(xyz111* o,int k)
 70 {
 71     int l=0;
 72     if(o->ch[0]!=NULL) l=o->ch[0]->size;
 73     if(l<k&&l+o->num>=k) return o->value;
 74     if(l+o->num<k) return kth(o->ch[1],k-l-o->num);
 75     return kth(o->ch[0],k);
 76 }
 77 int main()
 78 {
 79     srand(time(0));
 80     scanf("%d %d\n",&n,&m);
 81     int b=0;
 82     for(int i=1;i<=n;++i)
 83     {
 84         char c;
 85         int x;
 86         scanf("%c %d\n",&c,&x);
 87         if(c=='I') 
 88         {
 89             if(x<m) continue;
 90             insert(root,x-s);
 91             ++b;
 92         }
 93         if(c=='A') s+=x;
 94         if(c=='S')
 95         {
 96             s-=x;
 97             dfs(root,m-s);
 98         }
 99         if(c=='F') if(root==NULL||x>root->size) printf("-1\n");else printf("%d\n",kth(root,root->size-x+1)+s);
100     }
101     if(root==NULL) printf("%d",b);else printf("%d",b-root->size);
102     return 0;
103 }
View Code

6、http://www.wikioi.com/problem/1296/ 

平衡树撸,用Treap的……

 1 #include<cstring>
 2 #include<algorithm>
 3 #include<cstdio>
 4 #include<ctime>
 5 using namespace std;
 6 const int maxn=32767;
 7 struct xyz111
 8 {
 9     xyz111* ch[2];
10     int value,key,size;
11     int cmp(int x)
12     {
13         if(value==x) return -1;
14         return value<x;
15     }
16     void maintain()
17     {
18         size=1;
19         if(ch[0]!=NULL) size+=ch[0]->size;
20         if(ch[1]!=NULL) size+=ch[1]->size;
21     }
22 };
23 xyz111* root=NULL;
24 int n;
25 void rorate(xyz111* &o,int d)
26 {
27     xyz111* k=o->ch[d^1];
28     o->ch[d^1]=k->ch[d];
29     k->ch[d]=o;
30     o->maintain();
31     k->maintain();
32     o=k;
33 }
34 void insert(xyz111* &o,int x)
35 {
36     if(o==NULL)
37     {
38         o=new xyz111();
39         o->ch[0]=o->ch[1]=NULL;
40         o->value=x;
41         o->size=1;
42         o->key=rand()%100000000;
43     }
44     else
45     {
46         int d=o->cmp(x);
47         if(d==-1) return;
48         insert(o->ch[d],x);
49         if(o->ch[d]->key>o->key) rorate(o,d^1);
50     }
51     o->maintain();
52 }
53 int kth(xyz111* o,int k)
54 {
55     int l=0;
56     if(o->ch[0]!=NULL) l=o->ch[0]->size;
57     if(l+1==k) return o->value;
58     if(l+1>k) return kth(o->ch[0],k);
59     return kth(o->ch[1],k-l-1);
60 }
61 int rank(xyz111* o,int x)
62 {
63     if(o==NULL) return 0;
64     int d=o->cmp(x),l=0;
65     if(o->ch[0]!=NULL) l=o->ch[0]->size;
66     if(d==-1) return l+1;
67     if(d==0) return rank(o->ch[0],x);
68     return l+1+rank(o->ch[1],x);
69 }
70 int main()
71 {
72     scanf("%d",&n);
73     int ans;
74     scanf("%d",&ans);
75     insert(root,ans);
76     for(int i=2;i<=n;++i)
77     {
78         int x;
79         scanf("%d",&x);
80         int k=rank(root,x);
81         if(k==0) ans+=kth(root,1)-x;
82         else
83             if(k==root->size) ans+=x-kth(root,root->size);
84             else
85                 ans+=min(x-kth(root,k),kth(root,k+1)-x);
86         insert(root,x);
87     }
88     printf("%d",ans);
89     return 0;
90 }
View Code

7、http://www.lydsy.com/JudgeOnline/problem.php?id=1798

线段树成段更新,有乘法和加法 

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 using namespace std;
 5 const int maxn=100000;
 6 struct xyz111
 7 {
 8     int l,r;
 9     long long add,mult,sum;
10 }tree[4*maxn+50];
11 int n,p,m;
12 void build(int k,int l,int r)
13 {
14     tree[k].l=l,tree[k].r=r,tree[k].add=0,tree[k].mult=1;
15     if(l==r) scanf("%d",&tree[k].sum);
16     else
17     {
18         int mid=(l+r)/2;
19         build(k*2,l,mid);
20         build(k*2+1,mid+1,r);
21         tree[k].sum=tree[k*2].sum+tree[k*2+1].sum;
22     }
23 }
24 void maintain(int k,long long add,long long mult)
25 {
26     if(tree[k].l==0&&tree[k].r==0) return;
27     tree[k].mult=(tree[k].mult*mult)%p;
28     tree[k].add=((tree[k].add*mult)%p+add)%p;
29     tree[k].sum=((tree[k].sum+(tree[k].sum*(mult-1))%p)%p+(add*(tree[k].r-tree[k].l+1))%p)%p;
30 }
31 void updata(int k,int l,int r,long long add,long long mult)
32 {
33     if(tree[k].l>r||tree[k].r<l||(tree[k].l==0&&tree[k].r==0)) return;
34     if(tree[k].l>=l&&tree[k].r<=r) maintain(k,add,mult);
35     else
36     {
37         int mid=(tree[k].l+tree[k].r)/2;
38         maintain(k*2,tree[k].add,tree[k].mult);
39         maintain(k*2+1,tree[k].add,tree[k].mult);
40         tree[k].mult=1,tree[k].add=0;
41         updata(k*2,l,r,add,mult);
42         updata(k*2+1,l,r,add,mult);
43         tree[k].sum=(tree[k*2].sum+tree[k*2+1].sum)%p;
44     }
45 }
46 int ask(int k,int l,int r)
47 {
48     if(tree[k].l>r||tree[k].r<l||(tree[k].l==0&&tree[k].r==0)) return 0;
49     if(tree[k].l>=l&&tree[k].r<=r) return tree[k].sum;
50     int mid=(tree[k].l+tree[k].r)/2;
51     maintain(k*2,tree[k].add,tree[k].mult);
52     maintain(k*2+1,tree[k].add,tree[k].mult);
53     tree[k].mult=1,tree[k].add=0;
54     return (ask(k*2,l,r)+ask(k*2+1,l,r))%p;
55 }
56 int main()
57 {
58     scanf("%d %d",&n,&p);
59     for(int k=1;k<=4*n;++k)    tree[k].l=tree[k].r=0,tree[k].add=0,tree[k].mult=1,tree[k].sum=0;
60     build(1,1,n);
61     int k=1;
62     scanf("%d",&m);
63     for(int i=1;i<=m;++i)
64     {
65         int a,b,c,d;
66         scanf("%d",&a);
67         if(a==3) 
68         {
69             scanf("%d %d",&b,&c);
70             printf("%d\n",ask(1,b,c));
71             continue;
72         }
73         scanf("%d %d %d",&b,&c,&d);
74         if(a==1) updata(1,b,c,0,d);else updata(1,b,c,d,1); 
75     }
76     k=1;
77     return 0;
78 }
View Code

 8、http://codevs.cn/problem/3303/

splay维护数列的简单问题

 1 #include<cstring>
 2 #include<algorithm>
 3 #include<cstdio>
 4 using namespace std;
 5 const int maxn=100000;
 6 int pre[maxn+50],ch[maxn+50][2],flip[maxn+50],key[maxn+50],size[maxn+50];
 7 int n,m,root=0,len=0;
 8 void update(int k)
 9 {
10     size[k]=size[ch[k][0]]+size[ch[k][1]]+1;
11 }
12 void pushdown(int k)
13 {
14     if(flip[k]==0) return;
15     flip[k]=0;
16     swap(ch[k][0],ch[k][1]);
17     flip[ch[k][0]]^=1;
18     flip[ch[k][1]]^=1;
19 }
20 void rorate(int k,int d)
21 {
22     int f=pre[pre[k]],p=pre[k];
23     pushdown(p),pushdown(k);
24     ch[p][d^1]=ch[k][d];
25     pre[ch[k][d]]=p;
26     ch[k][d]=p;
27     pre[k]=f;
28     pre[p]=k;
29     if(f) ch[f][ch[f][1]==p]=k;else root=k;
30     update(p),update(k);
31 }
32 void splay(int x,int goal)
33 {
34     while(pre[x]!=goal)
35     {
36         pushdown(x);
37         if(pre[pre[x]]==goal) rorate(x,ch[pre[x]][0]==x);
38         else
39         {
40             int d1=ch[pre[x]][0]==x,d2=ch[pre[pre[x]]][0]==pre[x];
41             if(d1==d2) rorate(pre[x],d2),rorate(x,d1);
42             else rorate(x,d1),rorate(x,d2);
43         }
44     }
45     update(x);
46     if(goal==0) root=x;
47 }
48 void insert(int v)
49 {
50     int k=root;
51     while(ch[k][1]!=0) k=ch[k][1];
52     ++len;
53     pre[len]=k,ch[len][0]=ch[len][1]=0,flip[len]=0,key[len]=v,size[len]=1,ch[k][1]=len;
54     if(root==0) root=k;
55     splay(len,0);
56 }
57 void find(int k,int goal)
58 {
59     int t=root;
60     while(true)
61     {
62         pushdown(t);
63         if(size[ch[t][0]]+1==k) break;
64         if(k<=size[ch[t][0]]) t=ch[t][0];else k-=size[ch[t][0]]+1,t=ch[t][1];
65     }
66     splay(t,goal);
67 }
68 void ask(int k)
69 {
70     if(k==0) return;
71     pushdown(k);
72     ask(ch[k][0]);
73     if(key[k]>=2&&key[k]<=n+1)printf("%d ",key[k]-1);
74     ask(ch[k][1]);
75 }
76 int main()
77 {
78     scanf("%d %d",&n,&m);
79     for(int i=1;i<=n+2;++i)  insert(i);
80     splay((n+2)/2,0);
81     for(int i=1;i<=m;++i)
82     {
83         int x,y;
84         scanf("%d %d",&x,&y);
85         x+=1,y+=1;
86         find(x-1,0);
87         find(y+1,root);
88         flip[ch[ch[root][1]][0]]^=1;
89     }
90     ask(root);
91     return 0;
92 }
View Code

 9、http://www.lydsy.com:808/JudgeOnline/problem.php?id=2002

link-cut tree模板

  1 #include<cstring>
  2 #include<algorithm>
  3 #include<vector>
  4 #include<cstdio>
  5 using namespace std;
  6 const int maxn=200000;
  7 bool root[maxn+50];//root[i]表示节点i是否为它所在辅助树的根
  8 int father[maxn+50],size[maxn+50],ch[maxn+50][2];
  9 //father[i]记录i的父亲,他的父亲可能跟i在一个辅助树上也可能不在;size[i]表示在i所在的辅助树中以i为子树的节点个数;ch[i][0..1]记录的是i在辅助树中的左儿子和右儿子,如果没有用0表示
 10 int n,m;
 11 void update(int k)
 12 {
 13     if(k==0) return;
 14     size[k]=size[ch[k][0]]+size[ch[k][1]]+1;
 15 }
 16 void rorate(int k,int d)
 17 {
 18     int p=father[k],f=father[father[k]];
 19     ch[p][d^1]=ch[k][d];
 20     father[ch[k][d]]=p;
 21     ch[k][d]=p;
 22     father[p]=k;
 23     father[k]=f;
 24     if(f) 
 25         if(ch[f][0]==p) ch[f][0]=k;else if(ch[f][1]==p) ch[f][1]=k;//此处一定要注意,因为可能f和k不在一个辅助树上
 26     update(p);
 27     update(k);
 28     if(root[p]) root[k]=1,root[p]=0;//root[p]=0一定要记得加上
 29 }
 30 void splay(int k)
 31 {
 32     while (!root[k])
 33     {
 34         if(root[father[k]]) rorate(k,ch[father[k]][0]==k);
 35         else
 36         {
 37             int d1=ch[father[k]][0]==k,d2=ch[father[father[k]]][0]==father[k];
 38             if(d1==d2) rorate(father[k],d2),rorate(k,d1);else rorate(k,d1),rorate(k,d2);
 39         }
 40     }
 41     update(k);
 42 }
 43 void access(int x)
 44 {
 45     splay(x);
 46     while(father[x])
 47     {
 48         int y=father[x];
 49         splay(y);
 50         root[ch[y][1]]=1;
 51         root[x]=0;
 52         ch[y][1]=x;
 53         update(y);
 54         splay(x);
 55     }
 56 }
 57 void cut(int x)
 58 {
 59     access(x);
 60     splay(x);
 61     father[ch[x][0]]=0;
 62     root[ch[x][0]]=1;
 63     ch[x][0]=0;
 64     update(x);
 65 }
 66 void link(int x,int y)
 67 {
 68     if(y>n) y=n+1;
 69     father[x]=y;
 70 }
 71 int main()
 72 {
 73     freopen("ce.in","r",stdin);
 74     freopen("ce.out","w",stdout);
 75     scanf("%d",&n);
 76     for(int i=1;i<=n;++i) 
 77     {
 78         scanf("%d",&father[i]);
 79         father[i]+=i;
 80         if(father[i]>n) father[i]=n+1;
 81     }
 82     scanf("%d",&m);
 83     memset(size,0,sizeof(size));
 84     for(int i=1;i<=n+1;++i) size[i]=1;
 85     memset(root,1,sizeof(root));
 86     memset(ch,0,sizeof(ch));
 87     for(int i=1;i<=m;++i)
 88     {
 89         int x,y,z;
 90         scanf("%d %d",&x,&y);
 91         ++y;
 92         if(x==1)
 93         {
 94             access(y);
 95             printf("%d\n",size[ch[y][0]]);
 96         }
 97         else
 98         {
 99             scanf("%d",&z);
100             cut(y);
101             link(y,y+z);
102         }
103     }
104     return 0;
105 }
106             
View Code

10、还是上一题

分块模板 

 1 #include<cstring>
 2 #include<algorithm>
 3 #include<cstdio>
 4 #include<vector>
 5 #include<cmath>
 6 using namespace std;
 7 const int maxn=200000;
 8 int k[maxn+50],block[maxn+50],next[maxn+50],step[maxn+50];
 9 int n,m,l;
10 //block[i]计数i所处的块的编号;next[i]表示i一直往后跳直到跳出当前块的位置;step[i]表示i到next[i]要跳几步
11 void build(int l,int r)
12 {
13     for(int i=r;i>=l;--i)
14         if(i+k[i]>n) next[i]=0,step[i]=1;
15         else
16             if(block[i]==block[i+k[i]]) next[i]=next[i+k[i]],step[i]=step[i+k[i]]+1;
17             else next[i]=i+k[i],step[i]=1;
18 }//build(l,r)表示把[l,r]这一段重新维护一下
19 void ask(int x)
20 {
21     int s=0;
22     while(x)
23     {
24         s+=step[x];
25         x=next[x];
26     }
27     printf("%d\n",s);
28 }
29 int main()
30 {
31     freopen("ce.in","r",stdin);
32     freopen("ce.out","w",stdout);
33     scanf("%d",&n);
34     l=int(sqrt(n));
35     for(int i=1;i<=n;++i) scanf("%d",&k[i]),block[i]=(i-1)/l+1;
36     build(1,n);
37     scanf("%d",&m);
38     for(int i=1;i<=m;++i)
39     {
40         int x,y,z;
41         scanf("%d %d",&x,&y);
42         ++y;
43         if(x==1) ask(y);else scanf("%d",&z),k[y]=z,build(l*(block[y]-1)+1,y);
44     }
45     return 0;
46 }
View Code

 11、http://www.lydsy.com:808/JudgeOnline/problem.php?id=1036

树链剖分模板

  1 #include<cstring>
  2 #include<algorithm>
  3 #include<cstdio>
  4 #include<vector>
  5 using namespace std;
  6 const int maxn=30000,inf=1e9;
  7 struct wjmzbmr
  8 {
  9     int tid,top,size,son,dep,father,v;
 10 }tree[maxn+50];
 11 struct fotile96
 12 {
 13     int maxnum,sum;
 14 }f[4*maxn+50];
 15 vector<int> g[maxn+50];
 16 int pos[maxn+50];
 17 int n,label=0,q;
 18 void dfs(int x,int fa,int dep)
 19 {
 20     tree[x]=(wjmzbmr){0,0,1,0,dep,fa,tree[x].v};
 21     int m=0;
 22     for(int i=0;i<g[x].size();++i)
 23         if(g[x][i]!=fa)
 24         {
 25             dfs(g[x][i],x,dep+1);
 26             tree[x].size+=tree[g[x][i]].size;
 27             if(tree[g[x][i]].size>m) m=tree[g[x][i]].size,tree[x].son=g[x][i];
 28         }
 29 }
 30 void connect(int x,int top)
 31 {
 32     tree[x].tid=++label,pos[tree[x].tid]=x;
 33     tree[x].top=top;
 34     if(tree[x].son!=0) connect(tree[x].son,top);
 35     for(int i=0;i<g[x].size();++i)
 36         if(g[x][i]!=tree[x].father&&g[x][i]!=tree[x].son) connect(g[x][i],g[x][i]);
 37 }
 38 void make(int k,int l,int r)
 39 {
 40     if(l>r) return;
 41     if(l==r) f[k].maxnum=f[k].sum=tree[pos[l]].v;
 42     else
 43     {
 44         int mid=(l+r)>>1;
 45         make(k*2,l,mid);
 46         make(k*2+1,mid+1,r);
 47     f[k].sum=f[k*2].sum+f[k*2+1].sum;
 48     f[k].maxnum=max(f[k*2].maxnum,f[k*2+1].maxnum);
 49     }
 50 }
 51 void change(int k,int l,int r,int x,int y)
 52 {
 53     if(l>r||r<x||l>x) return;
 54     if(l==r)
 55     {
 56         if(l==x) f[k].maxnum=y,f[k].sum=y;
 57         return;
 58     }
 59     int mid=(l+r)>>1;
 60     change(k*2,l,mid,x,y);
 61     change(k*2+1,mid+1,r,x,y);
 62     f[k].sum=f[k*2].sum+f[k*2+1].sum;
 63     f[k].maxnum=max(f[k*2].maxnum,f[k*2+1].maxnum);
 64 }
 65 int qqmax(int k,int l,int r,int ll,int rr)
 66 {
 67     if(l>r||l>rr||r<ll) return -inf;
 68     if(l>=ll&&r<=rr) return f[k].maxnum;
 69     int mid=(l+r)>>1;
 70     return max(qqmax(k*2,l,mid,ll,rr),qqmax(k*2+1,mid+1,r,ll,rr));
 71 }
 72 int qmax(int x,int y)
 73 {
 74     int ans=-inf;
 75     while(tree[x].top!=tree[y].top)
 76     {
 77         if(tree[tree[x].top].dep<tree[tree[y].top].dep) swap(x,y);
 78         ans=max(ans,qqmax(1,1,n,tree[tree[x].top].tid,tree[x].tid));
 79         x=tree[tree[x].top].father;
 80     }
 81     if(tree[x].dep>tree[y].dep) swap(x,y);
 82     ans=max(ans,qqmax(1,1,n,tree[x].tid,tree[y].tid));
 83     return ans;
 84 }
 85 int qqsum(int k,int l,int r,int ll,int rr)
 86 {
 87     if(l>r||l>rr||r<ll) return 0;
 88     if(l>=ll&&r<=rr) return f[k].sum;
 89     int mid=(l+r)>>1;
 90     return qqsum(k*2,l,mid,ll,rr)+qqsum(k*2+1,mid+1,r,ll,rr);
 91 }
 92 int qsum(int x,int y)
 93 {
 94     int ans=0;
 95     while(tree[x].top!=tree[y].top)
 96     {
 97         if(tree[tree[x].top].dep<tree[tree[y].top].dep) swap(x,y);
 98         ans+=qqsum(1,1,n,tree[tree[x].top].tid,tree[x].tid);
 99         x=tree[tree[x].top].father;
100     }
101     if(tree[x].dep>tree[y].dep) swap(x,y);
102     ans+=qqsum(1,1,n,tree[x].tid,tree[y].tid);
103     return ans;
104 }
105 int main()
106 {
107     freopen("ce.in","r",stdin);
108     freopen("ce.out","w",stdout);
109     scanf("%d",&n);
110     for(int i=1;i<=n;++i) g[i].clear();
111     for(int i=1;i<n;++i) 
112     {
113         int x,y;
114         scanf("%d %d",&x,&y);
115         g[x].push_back(y);
116         g[y].push_back(x);
117     }
118     for(int i=1;i<=n;++i) scanf("%d",&tree[i].v);
119     dfs(1,0,0);
120     connect(1,1);
121     make(1,1,n);
122     scanf("%d\n",&q);
123     for(int i=1;i<=q;++i)
124     {
125         int x,y;
126         char s[10];
127         scanf("%s %d %d\n",s,&x,&y);
128         if(s[0]=='C') change(1,1,n,tree[x].tid,y);
129         if(s[1]=='M') printf("%d\n",qmax(x,y));
130         if(s[1]=='S') printf("%d\n",qsum(x,y));
131     }
132     return 0;
133 }
View Code

 12、SAP模版

 1 #include<cstring>
 2 #include<algorithm>
 3 #include<cstdio>
 4 #include<vector>
 5 using namespace std;
 6 const int maxn=20000,inf=1e8;
 7 struct wjmzbmr
 8 {
 9     int from,to,flow;
10 }E[maxn+50];
11 vector<int> g[maxn+50];
12 int n,m,len=-1;
13 int d[maxn+50,dv[maxn+50];
14 int dfs(int k,int flow)
15 {
16     if(k==n) return flow;
17     int f=0;
18     for(int i=0;i<g[k].size();++i)
19     {
20         wjmzbmr e=E[g[k][i]];
21         int k=dfs(e.to,min(flow-f,e.flow));
22         e.flow-=k;
23         E[g[k][i]^1].flow+=k;
24         f+=k;
25         if(f==flow) return f;
26     }
27     if(d[1]==n) return f;
28     --dv[d[k]];
29     if(dv[d[k]]==0) d[1]=n;
30     ++d[k];
31     ++dv[d[k]];
32 }
33 int main()
34 {
35     freopen("ce.in","r",stdin);
36     scanf("%d %d",&n,&m);
37     for(int i=1;i<=m;++i)
38     {
39         int a,b,c;
40         scanf("%d %d %d",&a,&b,&c);
41         ++len;
42         e[len]=(wjmzbmr){a,b,c};
43         g[a].push_back(len);
44         ++len;
45         e[len]=(wjmzbmr){b,a,0};
46         g[b].push_back(len);
47     }
48     for(int i=1;i<=n;++i) d[i]=n;
49     memset(dv,0,sizeof(dv));
50     dv[1]=n;
51     int ans=0;
52     while (d[1]<n)
53     {
54         ans+=dfs(1,inf);
55     }
56     return 0;
57 }
View Code

 

(未完待续)

posted @ 2014-07-21 23:04  Chellyutaha  阅读(246)  评论(0编辑  收藏  举报