1、求区间和

1 #include <cstdio>
2 #include <iostream>
3 using namespace std;
4 const int maxn=50000+5;
5 int a[maxn];
6 struct Node
7 {
8 int l,r,sum;
9 } node[maxn<<2];
10
11 //参数含义:节点区间,节点编号
12 void InitTree(int l,int r,int k)
13 {
14 node[k].r=r;//节点k的右子树
15 node[k].l=l;
16 node[k].sum=0;//权值
17 if(l==r)//到达叶子节点
18 {
19 node[k].sum=a[r];
20 return;
21 }
22 int mid=(l+r)>>1;
23 InitTree(l,mid,k<<1);//递归建左子树
24 InitTree(mid+1,r,k<<1|1);//递归建右子树
25
26 node[k].sum=node[k<<1].sum+node[k<<1|1].sum;
27 //父节点的值为两子节点值的和
28 //此为线段树的核心所在,求最值修改这一句即可
29 }
30 void UpdateTree(int l,int r,int k,int sum)
31 {
32 if(node[k].l==l&&node[k].r==r)
33 {
34 node[k].sum+=sum;
35 return;
36 }
37 int mid=(node[k].l+node[k].r)>>1;
38 if(l>mid)
39 UpdateTree(l,r,k<<1|1,sum);//更新下一层的右子树
40 else
41 UpdateTree(l,r,k<<1,sum);
42
43 node[k].sum=node[k<<1].sum+node[k<<1|1].sum;
44 //注意:每次更新后也要更新父节点的值
45 }
46 //查询l到r的k
47 int SearchTree(int l,int r,int k)
48 {
49 if(node[k].l==l&&node[k].r==r)
50 {
51 return node[k].sum;
52 }
53 int mid=(node[k].l+node[k].r)>>1;
54 if(l>mid)
55 {
56 return SearchTree(l,r,k<<1|1);//查询右子树
57 }
58 else if(r<=mid)
59 {
60 return SearchTree(l,r,k<<1);
61 }
62 else
63 {
64 //查询区间横跨左右子树,两棵子树一起查询
65 return SearchTree(mid+1,r,k<<1|1)+SearchTree(l,mid,k<<1);
66 }
67 }
68 int main()
69 {
70 int T,kase=0;
71 cin>>T;
72 while(T--)
73 {
74 printf("Case %d:\n",++kase);
75 int n,x,y;
76 scanf("%d",&n);
77 for(int i=1;i<=n;i++)
78 {
79 scanf("%d",&a[i]);
80 }
81 InitTree(1,n,1);
82 char ch[10];
83 while(scanf("%s",ch))
84 {
85 if(ch[0]=='E')
86 break;
87 scanf("%d%d",&x,&y);
88 if(ch[0]=='A')
89 UpdateTree(x,x,1,y);
90 else if(ch[0]=='S')
91 UpdateTree(x,x,1,-y);
92 else if(ch[0]=='Q')
93 cout<<SearchTree(x,y,1)<<endl;
94 }
95 }
96 return 0;
97 }
2、求区间最大值

1 #include <cstdio>
2 #include <iostream>
3 using namespace std;
4 const int maxn=200000+5;
5 int a[maxn];
6 struct Node
7 {
8 int l,r,sum;
9 } node[maxn<<2];
10
11 //参数含义:节点区间,节点编号
12 void InitTree(int l,int r,int k)
13 {
14 node[k].r=r;//节点k的右子树
15 node[k].l=l;
16 node[k].sum=0;//权值
17 if(l==r)//到达叶子节点
18 {
19 node[k].sum=a[r];
20 return;
21 }
22 int mid=(l+r)>>1;
23 InitTree(l,mid,k<<1);//递归建左子树
24 InitTree(mid+1,r,k<<1|1);//递归建右子树
25
26 node[k].sum=max(node[k<<1].sum,node[k<<1|1].sum);
27 //父节点的值为两子节点值的和
28 ///此为线段树的核心所在,求最值修改这一句即可
29 }
30 void UpdateTree(int l,int r,int k,int sum)
31 {
32 if(node[k].l==l&&node[k].r==r)
33 {
34 node[k].sum=sum;
35 return;
36 }
37 int mid=(node[k].l+node[k].r)>>1;
38 if(l>mid)
39 UpdateTree(l,r,k<<1|1,sum);//更新下一层的右子树
40 else
41 UpdateTree(l,r,k<<1,sum);
42
43 node[k].sum=max(node[k<<1].sum,node[k<<1|1].sum);
44 //注意:每次更新后也要更新父节点的值
45 }
46 //查询l到r的k
47 int SearchTree(int l,int r,int k)
48 {
49 if(node[k].l==l&&node[k].r==r)
50 {
51 return node[k].sum;
52 }
53 int mid=(node[k].l+node[k].r)>>1;
54 if(l>mid)
55 {
56 return SearchTree(l,r,k<<1|1);//查询右子树
57 }
58 else if(r<=mid)
59 {
60 return SearchTree(l,r,k<<1);
61 }
62 else
63 {
64 //查询区间横跨左右子树,两棵子树一起查询
65 return max(SearchTree(mid+1,r,k<<1|1),SearchTree(l,mid,k<<1));
66 }
67 }
68 int main()
69 {
70 int n,m;
71 while(scanf("%d%d",&n,&m)!=EOF)
72 {
73 int x,y;
74 for(int i=1;i<=n;i++)
75 {
76 scanf("%d",&a[i]);
77 }
78 InitTree(1,n,1);
79 char ch;
80 while(m--)
81 {
82 getchar();
83 scanf("%c",&ch);
84 scanf("%d%d",&x,&y);
85 if(ch=='U')
86 UpdateTree(x,x,1,y);
87 else if(ch=='Q')
88 printf("%d\n",SearchTree(x,y,1));
89 }
90 }
91 return 0;
92 }
3、更新版本(源自网络)(上面两个为更新结点,这个是更新区间)

1 #include <string.h>
2 #include <algorithm>
3 #include <stdio.h>
4 #include <math.h>
5 #include <queue>
6 #define MAXN 100010
7 #define inf 0x3f3f3f3f
8
9 using namespace std;
10
11 struct node{
12 long long l,r;//区间[l,r]
13 long long add;//区间的延时标记
14 long long sum;//区间和
15 // long long mx; //区间最大值
16 // long long mn; //区间最小值
17 }tree[MAXN<<2];//一定要开到4倍多的空间
18
19 void pushup(long long index){
20 tree[index].sum = tree[index<<1].sum+tree[index<<1|1].sum;
21 // tree[index].mx = max(tree[index<<1].mx,tree[index<<1|1].mx);
22 // tree[index].mn = min(tree[index<<1].mn,tree[index<<1|1].mn);
23 }
24 void pushdown(long long index){
25 //说明该区间之前更新过
26 //要想更新该区间下面的子区间,就要把上次更新该区间的值向下更新
27 if(tree[index].add){
28 //替换原来的值
29 /*
30 tree[index<<1].sum = (tree[index<<1].r-tree[index<<1].l+1)*tree[index].add;
31 tree[index<<1|1].sum = (tree[index<<1|1].r-tree[index<<1|1].l+1)*tree[index].add;
32 tree[index<<1].mx = tree[index].add;
33 tree[index<<1|1].mx = tree[index].add;
34 tree[index<<1].mn = tree[index].add;
35 tree[index<<1|1].mn = tree[index].add;
36 tree[index<<1].add = tree[index].add;
37 tree[index<<1|1].add = tree[index].add;
38 tree[index].add = 0;*/
39 //在原来的值的基础上加上val
40
41 tree[index<<1].sum += (tree[index<<1].r-tree[index<<1].l+1)*tree[index].add;
42 tree[index<<1|1].sum +=(tree[index<<1|1].r-tree[index<<1|1].l+1)*tree[index].add;
43 // tree[index<<1].mx += tree[index].add;
44 // tree[index<<1|1].mx += tree[index].add;
45 // tree[index<<1].mn += tree[index].add;
46 // tree[index<<1|1].mn += tree[index].add;
47 tree[index<<1].add += tree[index].add;
48 tree[index<<1|1].add += tree[index].add;
49 tree[index].add = 0;
50
51 }
52 }
53 void build(long long l,long long r,long long index){
54 tree[index].l = l;
55 tree[index].r = r;
56 tree[index].add = 0;//刚开始一定要清0
57 if(l == r){
58 scanf("%d",&tree[index].sum);
59 // tree[index].mn = tree[index].mx = tree[index].sum;
60 return ;
61 }
62 long long mid = (l+r)>>1;
63 build(l,mid,index<<1);
64 build(mid+1,r,index<<1|1);
65 pushup(index);
66 }
67 void updata(long long l,long long r,long long index,long long val){
68 if(l <= tree[index].l && r >= tree[index].r){
69 /*把原来的值替换成val,因为该区间有tree[index].r-tree[index].l+1
70 个数,所以区间和 以及 最值为:
71 */
72 /*tree[index].sum = (tree[index].r-tree[index].l+1)*val;
73 tree[index].mn = val;
74 tree[index].mx = val;
75 tree[index].add = val;//延时标记*/
76 //在原来的值的基础上加上val,因为该区间有tree[index].r-tree[index].l+1
77 //个数,所以区间和 以及 最值为:
78 tree[index].sum += (tree[index].r-tree[index].l+1)*val;
79 // tree[index].mn += val;
80 // tree[index].mx += val;
81 tree[index].add += val;//延时标记
82
83 return ;
84 }
85 pushdown(index);
86 long long mid = (tree[index].l+tree[index].r)>>1;
87 if(l <= mid){
88 updata(l,r,index<<1,val);
89 }
90 if(r > mid){
91 updata(l,r,index<<1|1,val);
92 }
93 pushup(index);
94 }
95 long long query(long long l,long long r,long long index){
96 if(l <= tree[index].l && r >= tree[index].r){
97 return tree[index].sum;
98 //return tree[index].mx;
99 //return tree[index].mn;
100 }
101 pushdown(index);
102 long long mid = (tree[index].l+tree[index].r)>>1;
103 long long ans = 0;
104 // long long Max = 0;
105 // long long Min = inf;
106 if(l <= mid){
107 ans += query(l,r,index<<1);
108 // Max = max(query(l,r,index<<1),Max);
109 // Min = min(query(l,r,index<<1),Min);
110 }
111 if(r > mid){
112 ans += query(l,r,index<<1|1);
113 // Max = max(query(l,r,index<<1|1),Max);
114 // Min = min(query(l,r,index<<1|1),Min);
115 }
116 return ans;
117 // return Max;
118 //return Min;
119 }
120 int main()
121 {
122 long long n,m,x,y,z;
123 char q;
124 scanf("%lld%lld",&n,&m);
125 build(1,n,1);
126 getchar();
127 while(m--){
128 scanf("%c",&q);
129 if(q == 'Q'){
130 scanf("%lld%lld",&x,&y);
131 printf("%lld\n",query(x,y,1));
132 }
133 else{
134 scanf("%lld%lld%lld",&x,&y,&z);
135 updata(x,y,1,z);
136 /* for(int i = 1; i <= n; ++i){
137 printf("a[%d] = %d\n",i,query(i,i,1));
138 }*/
139 }
140 getchar();
141 }
142 return 0;
143 }
来源:https://www.cnblogs.com/xxQ-1999/p/7606199.html
