poj3468-A Simple Problem with Integers
Time Limit: 5000MS | Memory Limit: 131072K | |
Total Submissions: 72128 | Accepted: 22254 | |
Case Time Limit: 2000MS |
Description
You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of operation is to add some given number to each number in a given interval. The other is to ask for the sum of numbers in a given interval.
Input
The first line contains two numbers N and Q. 1 ≤ N,Q ≤ 100000.
The second line contains N numbers, the initial values of A1, A2, ... , AN. -1000000000 ≤ Ai ≤ 1000000000.
Each of the next Q lines represents an operation.
"C a b c" means adding c to each of Aa, Aa+1, ... , Ab. -10000 ≤ c ≤ 10000.
"Q a b" means querying the sum of Aa, Aa+1, ... , Ab.
Output
You need to answer all Q commands in order. One answer in a line.
Sample Input
10 5 1 2 3 4 5 6 7 8 9 10 Q 4 4 Q 1 10 Q 2 4 C 3 6 3 Q 2 4
Sample Output
4 55 9 15
Hint
Source
POJ Monthly--2007.11.25, Yang Yi
splay tree
code:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <algorithm>
using namespace std;
#define rep(i, l, r) for (LL i = l; i <= r; i++)
#define REP(i, l, r) for (LL i = l; i >= r; i--)
#define null 0
#define LL long long
#define INF 1152921504606846976
#define MAXN 500010
struct tree {
tree *p, *ch[2];
LL sum, c, add, siz;
}*root, empty, fuck[MAXN];
LL n, T_T, num[MAXN], cnt = 0;
inline tree *kth(LL k) {
tree *f = root;
if (k < 1 || k > root->siz) return NULL;
for (; ; ) {
LL lc = f->ch[0] != null ? f->ch[0]->siz : 0;
LL rc = f->ch[1] != null ? f->ch[1]->siz : 0;
if (k == lc+1) return f;
if (k <= lc) f = f->ch[0];
else f = f->ch[1], k -= lc + 1;
}
}
inline void update(tree *x) {
x->siz = x->ch[0]->siz + x->ch[1]->siz + 1;
x->sum = x->ch[0]->sum + x->ch[1]->sum + x->c;
}
inline void pushdown(tree *x) {
if (!x->add) return;
if (x->ch[0]) {
x->ch[0]->add += x->add;
x->ch[0]->sum += x->ch[0]->siz * x->add;
x->ch[0]->c += x->add;
}
if (x->ch[1]) {
x->ch[1]->add += x->add;
x->ch[1]->sum += x->ch[1]->siz * x->add;
x->ch[1]->c += x->add;
}
x->add = 0;
}
inline void rotate(tree *x, LL t) {
tree *y = x->p;
pushdown(y);
pushdown(x);
y->ch[t] = x->ch[!t];
y->ch[t]->p = y;
x->p = y->p;
if (y == y->p->ch[0]) y->p->ch[0] = x;
else y->p->ch[1] = x;
y->p = x;
x->ch[!t] = y;
update(y);
update(x);
if (y == root) root = x;
}
inline void splay(tree *x, tree *y) {
pushdown(x);
while (x->p != y) {
if (x->p->p == y)
if (x == x->p->ch[0]) rotate(x, 0);
else rotate(x, 1);
else
if (x->p == x->p->p->ch[0])
if (x == x->p->ch[0]) rotate(x->p, 0), rotate(x, 0);
else rotate(x, 1), rotate(x, 0);
else
if (x == x->p->ch[1]) rotate(x->p, 1), rotate(x, 1);
else rotate(x, 0), rotate(x, 1);
}
update(x);
if (y == root->p) root = x;
}
inline tree *insert(LL *f, LL L, LL R) {
tree *r = fuck + ++cnt;
LL mid = (L + R) >> 1;
r->sum = r->c = f[mid];
r->siz = 1;
if (L <= mid-1) {
r->ch[0] = insert(f, L, mid-1);
r->siz += r->ch[0]->siz;
r->sum += r->ch[0]->sum;
}
else r->ch[0] = ∅
if (mid+1 <= R) {
r->ch[1] = insert(f, mid+1, R);
r->siz += r->ch[1]->siz;
r->sum += r->ch[1]->sum;
}
else r->ch[1] = ∅
r->ch[0]->p = r->ch[1]->p = r;
return r;
}
inline LL query_sum(LL L, LL R) {
splay(kth(L-1), root->p);
splay(kth(R+1), root);
pushdown(root->ch[1]->ch[0]);
return root->ch[1]->ch[0]->sum;
}
inline void modify(LL L, LL R, LL cx) {
splay(kth(L-1), root->p);
splay(kth(R+1), root);
root->ch[1]->ch[0]->c += cx;
root->ch[1]->ch[0]->add += cx;
root->ch[1]->ch[0]->sum += cx * root->ch[1]->ch[0]->siz;
}
int main() {
cin >> n >> T_T;
memset(num, 0, sizeof(num));
rep(i, 1, n) scanf("%lld", &num[i+1]);
root = insert(num, 1, n+2);
root->p = ∅
root->p->ch[0] = root->p->ch[1] = root;
while (T_T--) {
char ch[MAXN];
LL x, y, t;
scanf("%s", ch);
if (ch[0] == 'Q') scanf("%lld%lld", &x, &y), printf("%lld\n", query_sum(x+1, y+1));
if (ch[0] == 'C') scanf("%lld%lld%lld", &x, &y, &t), modify(x+1, y+1, t);
}
}