poj 3468

刷高代前的最后一道题,线段树的区间更新,这道题也让我管中窥豹般地观察到了线段树的一些深奥之处。

懒惰操作:我很懒,接收到更新操作后我先不着急更新,我先把自己的结点值更新了,为的是糊弄一部分查询操作,等到糊弄不过去不得不更新时我再更新,即要查询的区间比我维护的区间要更加地精确时。

这道题的话,注意下我注释的地方有溢出的可能性就行了

#include <iostream>
#include <cstdio>
using namespace std;
typedef long long ll;

const int N = 100100;

struct Segtree{
	int l, r;
	ll n, lazy;
}segtree[N * 4];

void pushup(int k){
	segtree[k]. n = segtree[k * 2]. n + segtree[k * 2 + 1]. n;
}

void pushdown(int k, int ln, int rn){
	if(segtree[k]. lazy){
		segtree[2 * k]. n += segtree[k]. lazy * ln;
		segtree[2 * k + 1]. n += segtree[k]. lazy * rn;
		segtree[2 * k]. lazy += segtree[k]. lazy;
		segtree[2 * k + 1]. lazy += segtree[k]. lazy;
		segtree[k]. lazy = 0; 
	}
}

void build(int k, int l, int r){
	segtree[k] = {l, r, 0, 0};
	if(l == r){
		scanf("%lld", &segtree[k]. n);
		return ;
	}
	int mid = (l + r) / 2;
	build(2 * k, l, mid);
	build(2 * k + 1, mid + 1, r);
	pushup(k);
}

void update(int k, int l, int r, int c){
	if(segtree[k]. l == l && segtree[k]. r == r){
		segtree[k]. n += ((ll)c) * (r - l + 1);  // 注意这个地方,有溢出的可能 
		segtree[k]. lazy += c;
		return ;
	}
	int mid = (segtree[k]. l + segtree[k]. r) / 2;
	pushdown(k, mid - segtree[k]. l + 1, segtree[k]. r - mid);
	if(r <= mid)
		update(2 * k, l, r, c);  
    else if(l > mid)
		update(2 * k + 1, l, r, c);  
    else{  
        update(2 * k, l, mid, c);  
        update(2 * k + 1, mid + 1, r, c);  
    }  
	pushup(k);
}

ll query(int k, int l, int r){
	if(l == segtree[k]. l && segtree[k]. r == r)
		return segtree[k]. n;
	int mid = (segtree[k]. l + segtree[k]. r) / 2;
	pushdown(k, mid - segtree[k]. l + 1, segtree[k]. r - mid);
	if(r <= mid)
		return query(k * 2, l, r); 
    else if(l > mid)
		return query(k * 2 + 1, l, r);  
    else
       return query(k * 2, l, mid) + query(k * 2 + 1, mid + 1, r);  
}

int main(){
	int n, q;
	while(~ scanf("%d%d", &n, &q)){
		build(1, 1, n);
		char c;
		int a, b, d;
		while(q --){
			cin >> c;
			if(c == 'Q'){
				scanf("%d%d", &a, &b);
				printf("%lld\n", query(1, a, b));
			}
			if(c == 'C'){
				scanf("%d%d%d", &a, &b, &d);
				update(1, a, b, d);
			}
		}
	}
	return 0;
}


好了,这一阶段到此为止了,明天开始开启高等代数的旅程

不知道下次回来时,会到达何种境界。

猜你喜欢

转载自blog.csdn.net/qq_38759433/article/details/80242654