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 }
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 }
②区间修改,查询区间最值区间求和
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 }
③区间替换,区间求和
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 }
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 }
时间: 2024-10-14 14:31:01