对应POJ 题目:点击打开链接
Time Limit: 5000MS | Memory Limit: 131072K | |
Total Submissions: 72765 | Accepted: 22465 | |
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
题意:
输入n,m;表示有n个数和m个询问。接着输入每个数的初始值。接着每个询问表示:Q表示求解i,j区间的和,C表示i~j区间的每个值都+k
思路:
Splay树区间更新问题,注意在更新标记后向上更新。
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <math.h> #define MAX(x, y) ((x) > (y) ? (x) : (y)) typedef struct TREE { long long sum; //以该结点为根的树的元素和 TREE *fa, *l, *r; int sz; //以该结点为根的树的总结点数 int add; //懒惰标记 }Tree; void Push_down(Tree *T) { if(NULL == T) return; if(T->add){ T->sum += ((long long)(T->sz) * T->add); if(T->l) T->l->add += T->add; if(T->r) T->r->add += T->add; T->add = 0; } } void Init(Tree *&T, int n) { int i; long long a; Tree *cur, *pre; pre = (Tree *)malloc(sizeof(Tree)); pre->sum = 0; pre->fa = pre->l = pre->r = NULL; pre->sz = 1; pre->add = 0; for(i = n - 1; i > -1; i--){ cur = (Tree *)malloc(sizeof(Tree)); scanf("%I64d", &a); cur->l = pre; cur->r = NULL; pre->fa = cur; cur->sz = pre->sz + 1; cur->sum = a + pre->sum; cur->add = 0; pre = cur; if(0 == i){ cur = (Tree *)malloc(sizeof(Tree)); cur->fa = NULL; cur->l = pre; cur->r = NULL; pre->fa = cur; cur->sz = pre->sz + 1; cur->sum = pre->sum; cur->add = 0; } } T = cur; } void R_rotate(Tree *x) { Tree *y = x->fa; Tree *z = y->fa; Tree *k = x->r; int sx = x->sz, sy = y->sz, sk = 0; long long sumx = x->sum, sumy = y->sum, sumk = 0; if(k){ Push_down(k); sk = k->sz; sumk = k->sum; } y->l = k; x->r = y; if(z){ if(y == z->l) z->l = x; else z->r = x; } if(k) k->fa = y; y->fa = x; x->fa = z; y->sz = sy - sx + sk; x->sz = sx - sk + y->sz; y->sum = sumy - sumx + sumk; x->sum = sumx - sumk + y->sum; } void L_rotate(Tree *x) { Tree *y = x->fa; Tree *z = y->fa; Tree *k = x->l; int sx = x->sz, sy = y->sz, sk = 0; long long sumx = x->sum, sumy = y->sum, sumk = 0; if(k){ Push_down(k); sk = k->sz; sumk = k->sum; } y->r = k; x->l = y; if(z){ if(y == z->r) z->r = x; else z->l = x; } if(k) k->fa = y; y->fa = x; x->fa = z; y->sz = sy - sx + sk; x->sz = sx - sk + y->sz; y->sum = sumy - sumx + sumk; x->sum = sumx - sumk + y->sum; } //寻找第x个数的结点 Tree *FindTag(Tree *T, int x) { if(NULL == T) return NULL; Push_down(T); Tree *p; p = T; int sum = (p->l ? p->l->sz : 0) + 1; while(sum != x && p) { if(sum < x){ p = p->r; x -= sum; } else p = p->l; Push_down(p); sum = (p->l ? p->l->sz : 0) + 1; } return p; } void Splay(int x, Tree *&T) { Push_down(T); Tree *p, *X, *end, *new_t; end = T->fa; new_t = T; if(end) new_t = T->fa; X = FindTag(new_t, x); while(X->fa != end) { p = X->fa; if(end == p->fa){ //p是根结点 if(X == p->l) R_rotate(X); else L_rotate(X); break; } //p不是根结点 if(X == p->l){ if(p == p->fa->l){ R_rotate(p); //LL R_rotate(X); //LL } else{ R_rotate(X); //RL L_rotate(X); } } else{ if(p == p->fa->r){ //RR L_rotate(p); L_rotate(X); } else{ //LR L_rotate(X); R_rotate(X); } } } T = X; } void FreeTree(Tree *T) { if(NULL == T) return; FreeTree(T->l); FreeTree(T->r); free(T); } void InOrder(Tree *T) { if(NULL == T) return; Push_down(T); InOrder(T->l); printf("%d ", T->sum); InOrder(T->r); } int main() { //freopen("in.txt", "r", stdin); Tree *T; T = NULL; int n, q; int a, b, c; char s[3]; scanf("%d%d", &n, &q); Init(T, n); while(q--) { //InOrder(T); //printf("\n"); scanf("%s", s); if('Q' == s[0]){ scanf("%d%d", &a, &b); a++; b++; Splay(a - 1, T); Splay(b + 1, T->r); Push_down(T->r->l); printf("%I64d\n", T->r->l->sum); } else{ scanf("%d%d%d", &a, &b, &c); a++; b++; Splay(a - 1, T); Splay(b + 1, T->r); T->r->l->add += c; //向上更新 T->r->sum += ((long long)(b - a + 1) * c); T->sum += ((long long)(b - a + 1) * c); } } FreeTree(T); return 0; }