线段树---poj3468 A Simple Problem with Integers:成段增减:区间求和

poj3468 A Simple Problem with Integers
题意:O(-1)
思路:O(-1)

线段树功能:update:成段增减 query:区间求和

Sample Input

10 5
1 2 3 4 5 6 7 8 9 10
Q 4 4
Q 1 10
Q 2 4
C 3 6 3
Q 2 4

Sample Output

4
55
9
15

Hint

The sums may exceed the range of 32-bit integers.

题目大意:  

N个数 M个操作 每个操作分Q a b得区间(a,b)的和;C a b c 区间[a,b]里面每个元素的value加c 

由于是成段更新 要用到延迟标记type; 每次C操作 只更新到和某个节点的区间范围一致,下次在访问的时候 延迟标记下移


#include <cstdio>
#include <algorithm>
using namespace std;
#define lson l , m , rt << 1
#define rson m + 1 , r , rt << 1 | 1
const int maxn = 111111;
struct Tree{
	__int64 value;
	__int64 type;
}tree[maxn<<2];


void PushUp(int rt) {
	tree[rt].value = tree[rt<<1].value + tree[rt<<1|1].value;
}
void PushDown(int rt,int ms) {
	if (tree[rt].type) {
		tree[rt<<1].type += tree[rt].type;
		tree[rt<<1|1].type += tree[rt].type ;
		tree[rt<<1].value += (ms - (ms >> 1)) * tree[rt].type;
		tree[rt<<1|1].value += (ms >> 1) * tree[rt].type;
		tree[rt].type = 0;
	}
}
void build(int l,int r,int rt) {
	tree[rt].type=0;
	__int64 val;
	if (l == r){
		scanf("%I64d",&val);
		tree[rt].value=val;
		return ;
	}
	int m = (l + r) >> 1;
	build(lson);
	build(rson);
	PushUp(rt);
}
void update(int L,int R,int c,int l,int r,int rt) {
	if (L <= l && r <= R) {//标记1  //更新到这就行,不一定更新到最底端
		tree[rt].type += c;
		tree[rt].value += c * (r - l + 1);
		return ;
	}
	PushDown(rt , r - l + 1);//延迟标记,这时候后推, (标记2)
	//比如建了 [1,4]  然后我们第一次的时候是更新[1,2]
	// [1,2][3,4]  [1,2]的type就是非0,value往上更新;
	//   [1][2][3][4]  第二次如果还是要更新[1,2] 在标记1直接更新
	int m = (l + r) >> 1;   // 而如果你是要更新[1,1](必定访问到标记2) 那么先进行标记2 让两儿子的value更新 
	if (L <= m) update(L , R , c , lson); //记得这时候儿子type被赋值,自己type=0;
	if (R > m) update(L , R , c , rson);
	PushUp(rt);
}
__int64 query(int L,int R,int l,int r,int rt) {  
    if (L <= l && r <= R) {  
        return tree[rt].value;  
    }  
	PushDown(rt , r - l + 1); //注意这里
    int m = (l + r) >> 1;     //如果之前标记[1,4]type!=0 然后我们现在
    __int64 ret = 0;         //如果是访问[1,4]第一步直接得到返回值是没有问题
    if (L <= m) ret += query(L , R , lson);  //但访问[1,3]的时候要要把之前的[1,4]延迟标记下移
    if (R > m) ret += query(L , R , rson);  
    return ret;  
}  
int main() {
	int N , Q;
	scanf("%d%d",&N,&Q);
	build(1 , N , 1);
	while (Q --) {
		char op[2];
		int a , b , c;
		scanf("%s",op); //防止用%c 会接受回车 新技能get√
		if (op[0] == 'Q') {
			scanf("%d%d",&a,&b);
			printf("%lld
",query(a , b , 1 , N , 1));
		} else {
			scanf("%d%d%d",&a,&b,&c);
			update(a , b , c , 1 , N , 1);
		}
	}
	return 0;
}


版权声明:本文为博主原创文章,未经博主允许不得转载。

today lazy . tomorrow die .
原文地址:https://www.cnblogs.com/france/p/4808773.html