POJ - 3468 - A Simple Problem with Integers (线段树 - 成段更新)


题目传送:A Simple Problem with Integers


思路:线段树,成段增减,区间求和,注意延迟标记需要累加,还有会爆int


AC代码:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define LL long long
#define INF 0x7fffffff
using namespace std;

const int maxn = 100005;
LL sum[maxn << 2];
LL lazy[maxn << 2];

void pushdown(int rt, int m) {
	if(lazy[rt] != 0) {
		lazy[rt << 1] += lazy[rt];//延迟标记需累加,因为可能有别的区间在这里产生延迟标记 
		lazy[rt << 1 | 1] += lazy[rt];
		sum[rt << 1] += (m - (m >> 1)) * lazy[rt];//区间加减更新 
		sum[rt << 1 | 1] += (m >> 1) * lazy[rt];
		lazy[rt] = 0;//用完后记得置为0 
	}
}

void build(int l, int r, int rt) {//建树 
	lazy[rt] = 0;//延迟标记赋初值 
	if(l == r) {
		scanf("%I64d", &sum[rt]);//题目中说会爆int,用64位输入输出 
		return;
	}
	int mid = (l + r) >> 1;
	build(l, mid, rt << 1);
	build(mid + 1, r, rt << 1 | 1);
	sum[rt] = sum[rt << 1] + sum[rt << 1 | 1];
}

void update(int L, int R, int c, int l, int r, int rt) {//更新 
	if(L <= l && r <= R) {
		sum[rt] += (LL)(r - l + 1) * c;//虽然这里不会爆int,但是看到乘法要特别注意会不会爆int 
		lazy[rt] += c;//累加延迟标记 
		return;
	}
	pushdown(rt, r - l + 1);
	int mid = (l + r) >> 1;
	if(L <= mid) update(L, R, c, l, mid, rt << 1);
	if(R >= mid + 1) update(L, R, c, mid + 1, r, rt << 1 | 1);
	sum[rt] = sum[rt << 1] + sum[rt << 1 | 1];
}

LL query(int L, int R, int l, int r, int rt) {//查询 
	if(L <= l && r <= R) {
		return sum[rt];
	}
	pushdown(rt, r - l + 1);
	int mid = (l + r) >> 1;
	LL ret = 0;
	if(L <= mid) ret += query(L, R, l, mid, rt << 1);
	if(R >= mid + 1) ret += query(L, R, mid + 1, r, rt << 1 | 1);
	return ret;
}

int main() {
	int n, q;
	while(scanf("%d %d", &n, &q) != EOF) {
		build(1, n, 1);
		char op[10];
		int a, b, c;
		for(int i = 0; i < q; i ++) {
			scanf("%s", op);
			if(op[0] == 'Q') {
				scanf("%d %d", &a, &b);
				printf("%I64d\n", query(a, b, 1, n, 1));
			}
			else {
				scanf("%d %d %d", &a, &b, &c);
				update(a, b, c, 1, n, 1);
			}
		}
	}
	return 0;
}





你可能感兴趣的:(~~~~~~~~~~数据结构,POJ,BIT,&&,RMQ,&&,线段树)