线段树 区间更新 区间查询 poj3468 A Simple Problem with Integers

相比较于单点更新和单点查询来说

区间更新多了一个pushdown函数

代码如下

void pushdown(int root,int m){
	if(add[root]){
		add[root<<1] += add[root];
		add[root<<1 | 1] += add[root];
		sum[root<<1] += add[root]*(m-(m>>1));
		sum[root<<1 | 1] += add[root]*(m>>1);
		add[root] = 0;
	}
}
假如我们要更新(2,3)区间,区间每个值加val

(2,3)区间的子区间(2,2),(3,3)就也要更新

这时我们增加一个add标记

如果(2,3)区间的每个值要加val

向下的每个区间也要加val

就有

add[root<<1] += add[root];
		add[root<<1 | 1] += add[root];
之后的sum就根据这个区间的长度去更新
代码如下<pre name="code" class="cpp">/********************************************
Author         :Crystal
Created Time   :
File Name      :
********************************************/
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <climits>
#include <string>
#include <vector>
#include <cmath>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <sstream>
#include <cctype>
using namespace std;
typedef long long ll;
typedef pair<int ,int> pii;
#define MEM(a,b) memset(a,b,sizeof a)
#define CLR(a) memset(a,0,sizeof a);
const int inf = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
//#define LOCAL
int ans[500005];
ll add[500005];
ll sum[500006];
void pushup(int root){
	sum[root] = sum[root*2] + sum[root*2+1];
}
void pushdown(int root,int m){
	if(add[root]){
		add[root<<1] += add[root];
		add[root<<1 | 1] += add[root];
		sum[root<<1] += add[root]*(m-(m>>1));
		sum[root<<1 | 1] += add[root]*(m>>1);
		add[root] = 0;
	}
}
void build(int l,int r,int root){
	add[root] = 0;
	if(l == r){
		scanf("%lld",&sum[root]);
		return;
	}
	int m = (l+r)>>1;
	build(l,m,root*2);
	build(m+1,r,root*2+1);
	pushup(root);
	return;
}
void update(int l,int r,int root,int ls,int rs,int val){
	if(l>=ls && r <= rs){
		sum[root] += (ll)val*(r-l+1);
		add[root] += val;
		return;
	}
	pushdown(root,r-l+1);
	int m = (l+r)>>1;
	if(ls <= m)update(l,m,root<<1,ls,rs,val);
	if(rs>m)update(m+1,r,root<<1|1,ls,rs,val);
	pushup(root);
}
ll query(int l,int r,int root,int ls,int rs){
	if(l>=ls && r <= rs){
		return sum[root];
	}
	pushdown(root,r-l+1);
	int m = (l+r)>>1;
	ll res = 0;
	if(ls <= m)res += query(l,m,root*2,ls,rs);
	if(rs > m)res += query(m+1,r,root*2+1,ls,rs);
	return res;
}
int main()
{
#ifdef LOCAL
	freopen("in.txt", "r", stdin);
//	freopen("out.txt","w",stdout);
#endif
	int n,m;
	while(cin >> n >> m){
		//cout << n << endl;
		build(1,n,1);
		for(int i=1;i<=m;i++){
			char q[10];
			scanf("%s",q);
			if(q[0]=='Q'){
				int a,b;scanf("%d%d",&a,&b);
				printf("%lld\n",query(1,n,1,a,b));
			}
			else{
				int a,b,c;
				scanf("%d%d%d",&a,&b,&c);
				update(1,n,1,a,b,c);
			}
		}
	}
	return 0;
}








 
 

你可能感兴趣的:(线段树)