题意: 给出一段序列,支持区间增减,区间查询。
解法: 数据结构成端更新的入门题了,这次又拿来试了试树状数组。
常数小果然飞起啊,splay 3907MS,线段树 1875MS,树状数组 969MS- -。
/* **********************************************
Author : Nero
Created Time: 2013-8-31 17:47:36
Problem id : POJ 3468
Problem Name: A Simple Problem with Integers
*********************************************** */
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define REP(i,a,b) for(int i=(a); i<(int)(b); i++)
#define clr(a,b) memset(a,b,sizeof(a))
typedef long long lld;
const int MAXN = 101000;
int n;
lld c[MAXN];
lld delta[MAXN];
lld deltai[MAXN];
void add(lld *t, int p, int d) {
for( ; p <= n; p += p&-p) t[p] += d;
}
lld sum(lld *t, int p) {
lld ret = 0;
for( ; p > 0; p -= p&-p) ret += t[p];
return ret;
}
lld query(int l, int r) {
lld ret = 0;
ret += c[r] + sum(delta, r) * (r+1) - sum(deltai, r);
ret -= c[l-1] + sum(delta, l-1) * l - sum(deltai, l-1);
return ret;
}
void update(int l, int r, int x) {
add(delta, l, x);
add(deltai, l, x * l);
add(delta, r+1, -x);
add(deltai, r+1, -x * (r+1));
}
int main() {
int nq,d;
while(~scanf("%d%d", &n, &nq)) {
clr(c,0);
clr(delta,0);
clr(deltai,0);
for(int i = 1; i <= n; i ++) {
scanf("%lld", &c[i]);
c[i] += c[i-1];
}
char s[10];
int a,b;
while(nq --) {
scanf("%s%d%d", s, &a, &b);
if(s[0] == 'Q') {
printf("%lld\n", query(a,b));
}
else {
int x;
scanf("%d", &x);
update(a,b,x);
}
}
}
return 0;
}