POJ 3468

线段树延迟标记的具体应用,是比较简单的区间加和修改

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>
using namespace std;

const int maxn= 1e5+5;
const int maxl= maxn<<2;

typedef long long ll;
ll tree[maxl], tag[maxl];
int a[maxn];
int s, e, d;

inline int LChild(int i)
{
	return i<<1;
}
inline int RChild(int i)
{
	return i<<1|1;
}
void Build(int rt, int l, int r)
{
	if (l> r){
		return;
	}
	if (l== r){
		tree[rt]= a[l];
		return;
	}
	int mid= (l+r)>>1, lc= LChild(rt), rc= RChild(rt);
	Build(lc, l, mid);
	Build(rc, mid+1, r);
	tree[rt]= tree[lc]+tree[rc];
}
void Init(int n)
{
	memset(tag, 0, sizeof(tag));
	Build(1, 1, n);
}
void Update(int rt, int l, int r)
{
	if (l== r){
		tree[rt]+= d;
		return;
	}

	tree[rt]= 0;
	int lc= LChild(rt), rc= RChild(rt);

	if (s<= l && r<= e){
		tag[rt]+= (ll)d;
	}
	else{
		int m= (l+r)>>1;
		if (s<= m){
			Update(lc, l, m);
		}
		if (m+1<= e){
			Update(rc, m+1, r);
		}
	}

	tree[rt]= tree[lc]+tree[rc]+tag[rt]*(ll)(r-l+1);
}
ll Query(int rt, int l, int r, ll ad)
{
	if (s<= l && r<= e){
		return tree[rt]+ad*(ll)(r-l+1);
	}

	int m= (l+r)>>1, lc= LChild(rt), rc= RChild(rt);
	ll rp= 0;
	if (s<= m){
		rp+= Query(lc, l, m, ad+tag[rt]);
	}
	if (m+1<= e){
		rp+= Query(rc, m+1, r, ad+tag[rt]);
	}

	return rp;
}

int main(int argc, char **argv)
{
	int n, q;
	char op;

	scanf("%d %d", &n, &q);
	for (int i= 1; i<= n; ++i){
		scanf("%d", a+i);
	}
	Init(n);

	while (q--){
		scanf(" %c", &op);

		if ('C'== op){
			scanf("%d %d %d", &s, &e, &d);
			Update(1, 1, n);
		}
		else{
			scanf("%d %d", &s, &e);
			cout<<Query(1, 1, n, 0)<<endl;
		}
	}

	return 0;
}
posted @ 2020-07-30 00:13  IdiotNe  阅读(111)  评论(0编辑  收藏  举报