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;
}