对应题目:点击打开链接
SPOJ - GSS6
Can you answer these queries VI
Description Given a sequence A of N (N <= 100000) integers, you have to apply Q (Q <= 100000) operations: InputThe first line of the input contains an integer N. OutputFor each "Q" operation, print an integer(one per line) as described above. ExampleInput: 5 3 -4 3 -1 6 10 I 6 2 Q 3 5 R 5 -4 Q 3 5 D 2 Q 1 5 I 2 -10 Q 1 6 R 2 -1 Q 1 6 Output: 8 3 6 3 5 |
题意:
开始有n个数,位置从1到n,
(I a, b) 表示在a位置插入数值b,
(D a) 表示把a位置的数删掉,
(R a, b) 表示把a位置的数换成数值b
(Q a, b) 表示求a位置到b位置之间的最大连续字段和
思路:
伸展树基本操作,结点信息有子树和sum, 前缀最大连续和lsum, 后缀最大连续和rsum, 子树最大连续和msum。主要是在push_up()的地方要注意下,认真仔细。
数组型:
#include <cstdio> #include <cstdlib> #include <cmath> #include <iostream> #define MAX(x, y) ((x)>(y)?(x):(y)) const int MAXN=200020; using namespace std; struct SplayTree { int val[MAXN]; int c[MAXN>>1]; int sz[MAXN]; int Left[MAXN]; int Right[MAXN]; int fa[MAXN]; int msum[MAXN]; int lsum[MAXN]; int rsum[MAXN]; int sum[MAXN]; int rt, Size, nil, inf; SplayTree() { rt = Size = nil = 0; inf = 1000000000; } inline void Push_up(int T) { sz[T] = sz[Left[T]] + sz[Right[T]] + 1; sum[T] = sum[Left[T]] + sum[Right[T]] + val[T]; msum[T] = lsum[T] = rsum[T] = val[T]; lsum[T] = MAX(lsum[Left[T]], sum[Left[T]] + val[T] + MAX(lsum[Right[T]], 0)); rsum[T] = MAX(rsum[Right[T]], sum[Right[T]] + val[T] + MAX(rsum[Left[T]], 0)); msum[T] = MAX(MAX(msum[Left[T]], msum[Right[T]]), val[T] + MAX(lsum[Right[T]], 0) + MAX(rsum[Left[T]], 0)); } void R_rotate(int x) { int y = fa[x]; int z = fa[y]; int k = Right[x]; Left[y] = k; Right[x] = y; if(nil != z){ if(y == Left[z]) Left[z] = x; else Right[z] = x; } if(nil != k) fa[k] = y; fa[y] = x; fa[x] = z; Push_up(y); } void L_rotate(int x) { int y = fa[x]; int z = fa[y]; int k = Left[x]; Right[y] = k; Left[x] = y; if(nil != z){ if(y == Right[z]) Right[z] = x; else Left[z] = x; } if(nil != k) fa[k] = y; fa[y] = x; fa[x] = z; Push_up(y); } int FindTag(int x) { if(nil == rt) return nil; int p = rt; int sum = sz[Left[p]] + 1; while(sum != x) { if(sum < x){ p = Right[p]; x -= sum; } else p = Left[p]; if(nil == p) break; sum = sz[Left[p]] + 1; } return p; } void Splay(int x, int &T) { int p, end; end = fa[T]; while(end != fa[x]) { p = fa[x]; if(end == fa[p]){ //p是根结点 if(x == Left[p]) R_rotate(x); else L_rotate(x); break; } //p不是根结点 if(x == Left[p]){ if(p == Left[fa[p]]){ R_rotate(p); //LL R_rotate(x); //LL } else{ R_rotate(x); //RL L_rotate(x); } } else{ if(p == Right[fa[p]]){ //RR L_rotate(p); L_rotate(x); } else{ //LR L_rotate(x); R_rotate(x); } } } T = x; Push_up(T); } inline void NewNode(int pre, int &T, int v) { T = ++ Size; fa[T] = pre; sz[T] = 1; Left[T] = Right[T] = nil; sum[T] = msum[T] = lsum[T] = rsum[T] = val[T] = v; } void MakeTree(int &T, int pre, int x, int y) { if(x > y) return; int mid = ((x + y)>>1); NewNode(pre, T, c[mid]); MakeTree(Left[T], T, x, mid - 1); MakeTree(Right[T], T, mid + 1, y); Push_up(T); } void Init(int n) { Left[0] = Right[0] = fa[0] = nil; sum[0] = 0; msum[0] = lsum[0] = rsum[0] = -inf; Size = 0; NewNode(nil, rt, -inf); NewNode(rt, Right[rt], inf); sz[rt] = 2; fa[rt] = 0; fa[rt] = nil; fa[Right[rt]] = rt; int i; for(i = 0; i < n; i++) scanf("%d", c + i); MakeTree(Left[Right[rt]], Right[rt], 0, n - 1); Push_up(Right[rt]); Push_up(rt); } void Insert(int pos, int v) { int t; t = FindTag(pos); Splay(t, rt); t = FindTag(pos + 1); Splay(t, Right[rt]); NewNode(Right[rt], Left[Right[rt]], v); Push_up(Right[rt]); Push_up(rt); } void Delete(int pos) { int t; t = FindTag(pos); Splay(t, rt); t = FindTag(pos + 2); Splay(t, Right[rt]); Left[Right[rt]] = nil; Push_up(Right[rt]); Push_up(rt); } void Replace(int pos, int v) { int t = FindTag(pos + 1); Splay(t, rt); if(val[rt] != v){ //值不同才需要更新 val[rt] = v; Push_up(rt); } } void Query(int x, int y) { int t; t = FindTag(x); Splay(t, rt); t = FindTag(y + 2); Splay(t, Right[rt]); printf("%d\n", msum[Left[Right[rt]]]); } }; SplayTree spl; int main() { //freopen("in.txt","r",stdin); int n, m, a, b; char ord[3]; while(scanf("%d", &n) == 1) { spl.Init(n); scanf("%d", &m); while(m--) { scanf("%s", ord); if('I' == ord[0]){ scanf("%d%d", &a, &b); spl.Insert(a, b); } else if('D' == ord[0]){ scanf("%d", &a); spl.Delete(a); } else if('R' == ord[0]){ scanf("%d%d", &a, &b); spl.Replace(a, b); } else{ scanf("%d%d", &a, &b); spl.Query(a, b); } } } return 0; }
指针型:
#include <cstdio> #include <cstdlib> #include <string> #include <string.h> #include <cmath> #include <iostream> #define MAX(x, y) ((x)>(y)?(x):(y)) const int MAXN = 100010; using namespace std; typedef int Type; typedef struct TREE { Type val; Type sum; //以该结点为根的树的元素和 Type lsum; //以该结点为根的区间从左往右的最大连续和 Type rsum; //以该结点为根的区间从右往左的最大连续和 Type msum; //以该结点为根的区间的最大连续和 TREE *fa, *l, *r; int sz; //以该结点为根的树的总结点数 }Tree; struct SplayTree { public: SplayTree() { rt = NULL; Size = 0; inf = 1000000000; memset(c, 0, sizeof(c)); } ~SplayTree() { FreeTree(rt); } void Push_up(Tree *T) { T->sz = (T->l ? T->l->sz : 0) + (T->r ? T->r->sz : 0) + 1; T->sum = T->val + (T->l ? T->l->sum : 0) + (T->r ? T->r->sum : 0); T->msum = T->lsum = T->rsum = T->val; Type t; if(T->l && T->r){ T->lsum = MAX(T->l->lsum, T->l->sum + T->val + MAX(T->r->lsum, 0)); T->rsum = MAX(T->r->rsum, T->r->sum + T->val + MAX(T->l->rsum, 0)); T->msum = MAX(MAX(T->l->msum, T->r->msum), T->val + MAX(T->r->lsum, 0) + MAX(T->l->rsum, 0)); } else if(T->l) { T->lsum = MAX(T->l->lsum, T->l->sum + T->val); T->rsum = MAX(T->l->rsum, 0) + T->val; T->msum = MAX(T->l->msum, T->rsum); } else if(T->r) { T->rsum = MAX(T->r->rsum, T->r->sum + T->val); T->lsum = MAX(T->r->lsum, 0) + T->val; T->msum = MAX(T->r->msum, T->lsum); } } void NewNode(Tree *pre, Tree *&T, Type v) { T = (Tree *)malloc(sizeof(Tree)); T->sum = T->msum = T->lsum = T->rsum = T->val = v; T->sz = 1; T->fa = pre; T->l = T->r = NULL; } void MakeTree(Tree *&T, Tree *pre, int x, int y) { if(x > y) return; int mid = ((x + y)>>1); NewNode(pre, T, c[mid]); MakeTree(T->l, T, x, mid - 1); MakeTree(T->r, T, mid + 1, y); Push_up(T); } void Init(int n) { Size = n; NewNode(NULL, rt, -inf); NewNode(rt, rt->r, inf); rt->sz = 2; rt->r->fa = rt; int i; for(i = 0; i < n; i++) scanf("%d", c + i); MakeTree(rt->r->l, rt->r, 0, n - 1); Push_up(rt->r); Push_up(rt); } void R_rotate(Tree *x) { Tree *y = x->fa; Tree *z = y->fa; Tree *k = x->r; 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; Push_up(y); } void L_rotate(Tree *x) { Tree *y = x->fa; Tree *z = y->fa; Tree *k = x->l; 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; Push_up(y); } //寻找第x个数的结点 Tree *FindTag(int x) { if(NULL == rt) return NULL; Tree *p; p = rt; Type sum = (p->l ? p->l->sz : 0) + 1; while(sum != x) { if(sum < x){ p = p->r; x -= sum; } else p = p->l; if(NULL == p) break; sum = (p->l ? p->l->sz : 0) + 1; } return p; } void Splay(Tree *X, Tree *&T) { Tree *p, *end; end = T->fa; 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; Push_up(T); } void Insert(int pos, Type v) { Tree *t = FindTag(pos); Splay(t, rt); t = FindTag(pos + 1); Splay(t, rt->r); NewNode(rt->r, rt->r->l, v); Push_up(rt->r); Size++; } void Delete(int pos) { if(NULL == rt) return; Tree *t; t = FindTag(pos); Splay(t, rt); t = FindTag(pos + 2); Splay(t, rt->r); free(rt->r->l); rt->r->l = NULL; Push_up(rt->r); Push_up(rt); Size--; } void Replace(int pos, Type v) { Tree *t = FindTag(pos + 1); Splay(t, rt); if(rt->val != v){ //值不同才需要更新 rt->val = v; Push_up(rt); } } void Query(int x, int y) { Tree *t; t = FindTag(x); Splay(t, rt); t = FindTag(y + 2); Splay(t, rt->r); printf("%d\n", rt->r->l->msum); } void FreeTree(Tree *T) { if(NULL == T) return; FreeTree(T->l); FreeTree(T->r); free(T); } private: Type c[MAXN], inf; Tree *rt; int Size; }; SplayTree spl; int main() { //freopen("in.txt","r",stdin); int n, m; Type a, b; char ord[3]; while(scanf("%d", &n) == 1) { spl.Init(n); scanf("%d", &m); while(m--) { scanf("%s", ord); if('I' == ord[0]){ scanf("%d%d", &a, &b); spl.Insert(a, b); } else if('D' == ord[0]){ scanf("%d", &a); spl.Delete(a); } else if('R' == ord[0]){ scanf("%d%d", &a, &b); spl.Replace(a, b); } else{ scanf("%d%d", &a, &b); spl.Query(a, b); } } } return 0; }