现在的位置: 首页 > 综合 > 正文

POJ 3468 A Simple Problem with Integers (线段树)

2018年01月13日 ⁄ 综合 ⁄ 共 1440字 ⁄ 字号 评论关闭

题目类型  线段树 - 区间修改

题目意思
给出最多100000个数 现在有最多100000个操作
操作1  把 区间 [L,R]中的数加上一个数c
操作2  询问区间 [L,R]中的数的和是多少

解题方法
区间修改的线段树
注意懒惰标记的使用就行了
参考代码 - 有疑问的地方在下方留言 看到会尽快回复的
#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

#define ls (rt<<1)
#define rs ((rt<<1)|1)
#define mid ((l+r)>>1)

typedef long long LL;

const int maxn = 1e5 + 10;
LL sum[maxn*4], add[maxn*4];
int A[maxn];

void build(int rt, int l, int r) {
	if(l == r) {
		sum[rt] = A[l];
		return ;
	}
	build(ls, l, mid);
	build(rs, mid + 1, r);
	sum[rt] = sum[ls] + sum[rs];
}

void pushdown(int rt, int l, int r) {
	if(l != r) {
		if(add[rt]) {
			sum[ls] += (mid - l + 1) * add[rt]; add[ls] += add[rt];
			sum[rs] += (r - mid) * add[rt]; add[rs] += add[rt];
			add[rt] = 0;
		}
	}
}

void update(int rt, int l, int r, int L, int R, int c) {
	pushdown(rt, l, r);
	if(l == L && r == R) {
		sum[rt]+= (r-l+1)*c;
		add[rt] = c;
		return ;
	}
	if(R <= mid) update(ls, l, mid, L, R, c);
	else if(L > mid) update(rs, mid + 1, r, L, R, c);
	else update(ls, l, mid, L, mid, c), update(rs, mid + 1, r, mid + 1, R, c);
	sum[rt] = sum[ls] + sum[rs];
}

LL query(int rt, int l, int r, int L, int R) {
	pushdown(rt, l, r);
	if(l == L && r == R) return sum[rt];
	if(R <= mid) return query(ls, l, mid, L, R);
	else if(L > mid) return query(rs, mid + 1, r, L, R);
	else return query(ls, l, mid, L, mid) + query(rs, mid + 1, r, mid + 1, R);
	sum[rt] = sum[ls] + sum[rs];
}

int main() {
	freopen("in", "r", stdin);
	int n, m;
	while(scanf("%d%d", &n, &m) != EOF) {
		for( int i=0; i<n; i++ ) scanf("%d", &A[i]);
		build(1, 0, n);
		for( int i=0; i<m; i++ ) {
			char str[10];
			scanf("%s", str);
			if(str[0] == 'Q') {
				int l, r;
				scanf("%d%d", &l, &r);
				LL ans = query(1, 0, n, l-1, r-1);
				cout<<ans<<endl;
			}
			else {
				int l, r, c;
				scanf("%d%d%d", &l, &r, &c);
				update(1, 0, n, l-1, r-1, c);
			}
		}
	}
	return 0;
}

抱歉!评论已关闭.