对应题目:点击打开链接
SPOJ - GSS6
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;
}