(Relax 线段树1.1)POJ 3468 A Simple Problem with Integers(线段树子区间更新的维护:集中更新和动态统计子序列中的数据)


/*
 * POJ_3468.cpp
 *
 *  Created on: 2013年11月25日
 *      Author: Administrator
 */

#include <iostream>
#include <cstdio>

#define maxn 100010
#define Fup(i, s, t) for (int i = s; i <= t; i ++)
#define Fdn(i, s, t) for (int i = s; i >= t; i --)

using namespace std;

struct node {//线段树
	long long mark;//节点i的懒惰标记为tree[i].mark
	long long sum;//节点i的数和为tree[i].sum
} tree[maxn * 4];

int x[maxn];//初始值序列
int n;//数字个数
int m;//操作次数

void update(int l, int r, int i) {//标记法维护线段树(根为i,对应区间[l,r])
	if (!tree[i].mark)
		return;
	int mid = (l + r) / 2;
	tree[i + i].sum += tree[i].mark * (long long) (mid - l + 1);
	tree[i + i + 1].sum += tree[i].mark * (long long) (r - mid);
	tree[i + i].mark += tree[i].mark;
	tree[i + i + 1].mark += tree[i].mark;
	tree[i].mark = 0;
}

long long query(int tl, int tr, int l, int r, int i) {//计算线段树的数字和(根为i,对应区间[l,r]内子区间[tl,tr]的数字和)
	if (tl > r || tr < l)
		return 0;
	if (tl <= l && r <= tr)
		return tree[i].sum;
	update(l, r, i);
	int mid = (l + r) / 2;
	return query(tl, tr, l, mid, i + i) + query(tl, tr, mid + 1, r, i + i + 1);
}


//线段树中区间[l,r]的子区间[tl,tr]中的每个数+val
void add_value(int tl, int tr, int l, int r, int i, int val) {
	if (tl > r || tr < l)
		return;
	if (tl <= l && r <= tr) {
		tree[i].sum += val * (long long) (r - l + 1);
		tree[i].mark += val;
		return;
	}
	update(l, r, i);
	int mid = (l + r) / 2;
	add_value(tl, tr, l, mid, i + i, val);
	add_value(tl, tr, mid + 1, r, i + i + 1, val);
	tree[i].sum = tree[i + i].sum + tree[i + i + 1].sum;
}

//建立根为i,对应区间[1..n]的线段树
void build_tree(int l, int r, int i) {
	if (l == r) {
		tree[i].sum = x[l];
		return;
	}
	int mid = (l + r) / 2;
	build_tree(l, mid, i + i);
	build_tree(mid + 1, r, i + i + 1);
	tree[i].sum = tree[i + i].sum + tree[i + i + 1].sum;
}

void solve(){
	build_tree(1,n,1);//****别漏了,记得要先建线段数

	char ch;
	int i;
//	scanf("\n");
	for(i = 1 ; i <= m ; ++i){
		int l,r,v;
		scanf(" %c",&ch);
		if(ch == 'Q'){
			scanf("%d%d",&l,&r);

			long long ans = query(l,r,1,n,1);
			printf("%lld\n",ans);
//			cout<<ans<<endl;
		}else if(ch == 'C'){
			scanf("%d%d%d",&l,&r,&v);

			add_value(l,r,1,n,1,v);
		}
	}
}

int main(){
	while(scanf("%d%d",&n,&m)!=EOF){
		int i;
		for(i = 1 ; i <= n ; ++i){
			scanf("%d",&x[i]);
		}

		solve();
	}

	return 0;
}


你可能感兴趣的:((Relax 线段树1.1)POJ 3468 A Simple Problem with Integers(线段树子区间更新的维护:集中更新和动态统计子序列中的数据))