题目链接:http://poj.org/problem?id=3468
题意:
给出n个数,有q个操作,其中一种操作是将某个区间都加上某一个整数,另一个操作是询问某个区间的和。
思路:
线段树,区间更新,区间和查询。区间更新自然用到lazy-tag。模板题,关键还是理解模板。
注意数据范围
代码:
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cstdlib>
typedef long long LL;
using namespace std;
const int maxn = 100000;
LL add[4*maxn+5];
LL sum[4*maxn+5];
void up(int rt){
sum[rt] = sum[rt<<1] + sum[rt<<1|1];
return;
}
void down(int rt, int m){
if(add[rt]){
add[rt<<1] += add[rt];
add[rt<<1|1] += add[rt];
sum[rt<<1] += (m-(m>>1))*add[rt];
sum[rt<<1|1] += (m>>1)*add[rt];
add[rt] = 0;
}
return;
}
void build(int rt, int l, int r){
if(l==r){
scanf("%lld", &sum[rt]);
}
else{
int mid = (l+r)>>1;
build(rt<<1, l, mid);
build(rt<<1|1, mid+1, r);
up(rt);
}
return;
}
void update(int val, int rt, int l, int r, int x, int y){
if(x<=l && r<=y){
sum[rt] += (LL)(val*(r-l+1));
add[rt] += val;
}
else{
down(rt, r-l+1);
int mid = (l+r)>>1;
if(x<=mid) update(val, rt<<1, l, mid, x, y);
if(y>mid) update(val, rt<<1|1, mid+1, r, x, y);
up(rt);
}
return;
}
LL query(int rt, int l, int r, int x, int y){
if(x<=l && r<=y){
return sum[rt];
}
else{
down(rt, r-l+1);
int mid = (l+r)>>1;
LL ans = 0;
if(x<=mid) ans += query(rt<<1, l, mid, x, y);
if(y>mid) ans += query(rt<<1|1, mid+1, r, x, y);
return ans;
}
}
int main(){
char operat;
int n, q;
LL a, b, c;
while(scanf("%d%d", &n, &q)!=EOF){
memset(sum, 0, sizeof(sum));
memset(add, 0, sizeof(add));
build(1, 1, n);
for(int i=0; i<q; i++){
getchar();
scanf("%c", &operat);
if(operat=='C'){
scanf("%lld%lld%lld", &a, &b, &c);
update(c, 1, 1, n, a, b);
}
else{
scanf("%lld%lld", &a, &b);
printf("%lld\n", query(1, 1, n, a, b));
}
}
}
return 0;
}