码迷,mamicode.com
首页 > 其他好文 > 详细

抽象数据结构

时间:2015-09-25 18:20:25      阅读:258      评论:0      收藏:0      [点我收藏+]

标签:

1、树状数组

技术分享
 1 #include <cstdio>
 2 #include <cstdlib>
 3 #include <cstring>
 4 #include <cmath>
 5 #include <iostream>
 6 #include <algorithm>
 7 using namespace std;
 8 #define INF ~0U>>1
 9 
10 const int MAX=300;
11 int n,num[MAX],c[MAX],X,Y;
12 
13 int lowbit(int x){ return x&(-x);}
14 
15 int SUM(int l,int r){//区间查询 
16     int sum=0;
17 
18     for(int i=r;i;i-=lowbit(i)) sum+=c[i];
19     for(int i=l;i;i-=lowbit(i)) sum-=c[i];
20 
21     return sum;
22 }
23 
24 void change(int x,int m){ for(int i=x;i<=n;i+=lowbit(i)) c[i]+=m;}//单点修改 
25 
26 int main(){
27     memset(c,0,sizeof(c));
28 
29     cin >> n;
30     for(int i=1;i<=n;i++){
31         cin >> num[i];
32         for(int j=i-lowbit(i)+1;j<=i;j++) c[i]+=num[j];
33     }
34 
35     cout << "1 X Y:sum[Y]-sum[X](X<Y)" << endl << "2 X Y:num[X]=Y" << endl << "0:end" << endl;
36 
37     int i;
38     do{
39         cin >> i >> X >> Y;
40         if(!i) break;
41         if(i==1) cout << SUM(X,Y) << endl;
42         if(i==2) change(X,Y),cout << "FINISH!" << endl;
43     }while(i);
44 
45     return 0;
46 }
View Code

2、线段树

http://blog.csdn.net/metalseed/article/details/8039326

①单点修改替换,查询区间最值区间求和

技术分享
 1 #include<iostream>
 2 #include<algorithm>
 3 #define lson l,m,rt<<1
 4 #define rson m+1,r,rt<<1|1
 5 #define maxn 10000
 6 int n,rt,Max[maxn<<2],Min[maxn<<2],Sum[maxn<<2],a[maxn<<2];
 7 using namespace std;
 8 void pushup(int rt){
 9     Max[rt] = max(Max[rt<<1],Max[rt<<1|1]);
10     Min[rt] = min(Min[rt<<1],Min[rt<<1|1]);
11     Sum[rt] = Sum[rt<<1]+Sum[rt<<1|1];
12 }
13 void buildtree(int l,int r,int rt){
14     if(l == r){
15         Max[rt] = Min[rt] = Sum[rt] = a[l];
16         return;
17     }
18     int m = (l+r)>>1;
19     buildtree(lson);
20     buildtree(rson);
21     pushup(rt);
22 }
23 void setval(int p,int v,int l,int r,int rt){
24     if(l == r){
25         Max[rt] = Min[rt] = Sum[rt] = v;
26         return; 
27     }
28     int m = (l+r)>>1;
29     if(p <= m) update(p,v,lson);
30     else update(p,v,rson);
31     pushup(rt);
32 }
33 void addval(int p,int v,int l,int r,int rt){
34     if(l == r){
35         Max[rt] += v;
36         Min[rt] += v;
37         Sum[rt] += v;
38         return; 
39     }
40     int m = (l+r)>>1;
41     if(p <= m) update(p,v,lson);
42     else update(p,v,rson);
43     pushup(rt);
44 }
45 
46 int query_max(int L,int R,int l,int r,int rt){
47     if(L <= l && r <= R) return Max[rt];
48     int m = (l+r)>>1;
49     int ret = 0;
50     if(L <= m) ret = max(ret,query(L,R,lson));
51     if(R > m) ret = max(ret,query(L,R,rson));
52     return ret;
53 }
54 int query_min(int L,int R,int l,int r,int rt){
55     if(L <= l && r <= R) return Min[rt];
56     int m = (l+r)>>1;
57     int ret = 0;
58     if(L <= m) ret = min(ret,query(L,R,lson));
59     if(R > m) ret = min(ret,query(L,R,rson));
60     return ret;
61 }
62 int query_sum(int L,int R,int l,int r,int rt){
63     if(L <= l && r <= R) return Sum[rt];
64     int m = (l+r)>>1;
65     int ret = 0;
66     if(L <= m) ret += query(L,R,lson);
67     if(R > m) ret += query(L,R,rson);
68     return ret;
69 }
70 
71 int main(){
72     cin>>n;
73     buildtree(1,n,1);
74     return 0;
75 }
View Code

②区间修改,查询区间最值区间求和

技术分享
  1 #include<iostream>
  2 
  3 #include<algorithm>
  4 
  5 using namespace std;
  6 
  7 const long long int INF = 100000000;
  8 
  9 const int maxn = 2000000 + 10;
 10 
 11 long long int sumv[maxn], minv[maxn], maxv[maxn], addv[maxn];//sumv[]:如果只执行结点o及其子孙结点中的add操作,结点o对应区间中所有数之和
 12 
 13 long long int my_y1, my_y2, v, n, m;//修改/查询范围均为[my_y1,my_y2];
 14 
 15 void mantain(int o, int l, int r){
 16 
 17 int lc = o * 2, rc = o * 2 + 1;
 18 
 19 sumv[o] = minv[o] = maxv[o] = 0;
 20 
 21 if (r > l){//考虑左右子树
 22 
 23 sumv[o] = sumv[lc] + sumv[rc];
 24 
 25 minv[o] = min(minv[lc], minv[rc]);
 26 
 27 maxv[o] = max(maxv[lc], maxv[rc]);
 28 
 29 }
 30 
 31 minv[o] += addv[o]; maxv[o] += addv[o]; sumv[o] += addv[o] * (r - l + 1);
 32 
 33 //考虑add操作
 34 
 35 }
 36 
 37 //在执行add操作时,哪些结点需啊哟调用上述maintain函数呢?很简单,递归访问到的结点全部要调用,并且是在递归返回后调用。
 38 
 39 void update(int o, int l, int r){
 40 
 41 int lc = o * 2, rc = o * 2 + 1;
 42 
 43 if (my_y1 <= l&&my_y2 >= r){//递归边界
 44 
 45 addv[o] += v;
 46 
 47 }
 48 
 49 else{
 50 
 51 int m = l + (r - l) / 2;
 52 
 53 if (my_y1 <= m) update(lc, l, m);
 54 
 55 if (my_y2 > m) update(rc, m + 1, r);
 56 
 57 }
 58 
 59 mantain(o, l, r);
 60 
 61 }
 62 
 63 
 64 
 65 long long int _min, _max, _sum;//全局变量,目前位置的最小值、最大值和累加和
 66 
 67 void query(int o, int l, int r, int add){
 68 
 69 if (my_y1 <= l&&my_y2 >= r){//递归边界:用边界区间的附加信息更新答案
 70 
 71 _sum += sumv[o] + add*(r - l + 1);
 72 
 73 _min = min(_min, minv[o] + add);
 74 
 75 _max = max(_max, maxv[o] + add);
 76 
 77 }
 78 
 79 else{//递归统计,累加参数add
 80 
 81 int m = l + (r - l) / 2;
 82 
 83 if (my_y1 <= m) query(o * 2, l, m, add + addv[o]);
 84 
 85 if (my_y2 > m) query(o * 2 + 1, m + 1, r, add + addv[o]);
 86 
 87 
 88 
 89 }
 90 
 91 }
 92 
 93 int main(){
 94 
 95 int i, j;
 96 
 97 cin >> n;
 98 
 99 for (i = 1; i <= n; i++)
100 
101 {
102 
103 cin >> v;
104 
105 my_y1 = my_y2 = i;
106 
107 update(1, 1, n);
108 
109 }
110 
111 cin >> m;
112 
113 for (i = 1; i <= m; i++){
114 
115 int q;
116 
117 cin >> q;
118 
119 if (q == 1){
120 
121 cin >> my_y1 >> my_y2 >> v;
122 
123 update(1, 1, n);
124 
125 
126 
127 }
128 
129 else{
130 
131 int y;
132 
133 cin >> my_y1>>my_y2;
134 
135 _sum = 0; _min = INF; _max = -INF;
136 
137 query(1, 1, n, 0);
138 
139 cout << _sum << endl;
140 
141 }
142 
143 }
144 
145 system("pause");
146 
147 }
View Code

③区间替换,区间求和

技术分享
 1 #include<iostream>
 2 #include<algorithm>
 3 #define lson l,m,rt<<1
 4 #define rson m+1,r,rt<<1|1
 5 #define maxn 10000
 6 int n,rt,sum[maxn<<2],col[maxn<<2];//col是延迟标记 
 7 using namespace std;
 8 void pushup(int rt){
 9     sum[rt] = sum[rt<<1] + sum[rt<<1|1];//或min,max 
10 }
11 void pushdown(int rt,int m){
12     if(col[rt]){
13         col[rt<<1] = col[rt<<1|1] = col[rt];
14         sum[rt<<1] = (m-(m>>1)) * col[rt];
15         sum[rt<<1|1] = (m>>1) * col[rt];
16         col[rt] = 0;
17     }
18 }
19 void buildtree(int l,int r,int rt){
20     col[rt] = 0;
21     sum[rt] = 1;
22     if(l == r) return;
23     int m = (l+r)>>1;
24     buildtree(lson);
25     buildtree(rson);
26     pushup(rt);
27 }
28 void update(int L,int R,int c,int l,int r,int rt){
29     if(L <= l && r <= R){
30         col[rt] = c;
31         sum[rt] = c*(r-l+1);
32         return;
33     }
34     pushdown(rt,r-l+1);
35     int m = (l+r)>>1;
36     if(L <= m) update(L,R,c,lson);
37     if(R>m) update(L,R,c,rson);
38     pushup(rt);
39 }
40 int query(int L,int R,int l,int r,int rt){
41     if(L <= l && r <= R) return sum[rt];
42     int m = (l+r)>>1;
43     int ret = 0;
44     if(L <= m) ret += query(L,R,lson);
45     if(R > m) ret += query(L,R,rson);
46     return ret;
47 }
48 int main(){
49     cin>>n;//5
50     buildtree(1,n,1);//12345
51     update(1,5,2,1,n,1);
52     update(5,9,3,1,n,1);
53     cout<<query(1,n,1,n,1);
54     return 0;
55 }
View Code

 3、Spare Table

技术分享
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cmath>
 4 #include <algorithm>
 5 #include <cstdlib>
 6 #include <cstring>
 7 using namespace std;
 8 #define MAX 50010
 9 
10 int top,n,x,y;
11 int f[MAX*2][30],f2[MAX*2][30];
12 int seq[MAX*2];
13 
14 int rmq(){
15     int m=(int)(log((double)top-1)/log(2.0));
16 
17     for(int i=1;i<top;++i) f[i][0]=seq[i],f2[i][0]=seq[i];
18 
19     for(int j=1,k=1<<(j-1);j<=m;++j,k=1<<(j-1))
20         for(int i=1;i+(1<<(j-1))<top;++i){
21             f[i][j]=min(f[i][j-1],f[i+k][j-1]);
22             f2[i][j]=max(f2[i][j-1],f2[i+k][j-1]);
23         }
24 
25     return 0;
26 }
27 
28 int query(int l,int r){
29     int k=(int)(log(r-l+1.0)/log(2.0));
30 
31     if(l>r)swap(l,r);
32 
33     return max(f2[l][k],f2[r-(1<<k)+1][k])-min(f[l][k],f[r-(1<<k)+1][k]);
34 }
35 
36 int main(){
37     cin >> top >> n;
38     top++;
39 
40     for(int i=1;i<top;i++) cin >> seq[i];
41 
42     rmq();
43 
44     while(n--){
45         cin >> x >> y;
46         cout << query(x,y) << endl;
47     }
48 
49     return 0;
50 }
View Code

 

抽象数据结构

标签:

原文地址:http://www.cnblogs.com/hyfer/p/4838807.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!