Splay不加反转(Push_down)版本,求区间最大值,维护每个点的子树的整个sum和
中间(内部)最大值:msum,lsum(左侧连续最大值)rsum右侧连续最大值,和线段树基本一致)
splay(int &x,int pos)是指把现在x这个根的子树做变化,使得这个根变成这个子树里面第pos位(中序遍历)splay整棵树的中序遍历就是我们维护的动态数组,比如添加一个数到数组里第5个位置的时候,可以考虑根的左儿子有3个,根就是第4个,如果根的右儿子是第5个,那么显然根的右儿子的左儿子添加数字的话就正好插在整个树的第5个,操作就是把4先旋到整个树的根,再把旋完的跟的右子树的根旋成这个子树的第1个,这个左儿子就是空的了,把要插的插进去,其余操作都相同
/*
Splay不加反转(Push_down)版本,求区间最大值,维护每个点的子树的整个sum和
中间(内部)最大值:msum,lsum(左侧连续最大值)rsum右侧连续最大值,和线段树基本一致)
*/
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 200009;
const int inf = 2000000000+1;
int siz[maxn],s[maxn][2],tot,val[maxn],n,m;
int lsum[maxn]; //[left, x)
int rsum[maxn]; //(x, right]
int msum[maxn],sum[maxn]; //m:inside
#define ls s[x][0]
#define rs s[x][1]
int p,root;
int fd(int x,int k){//-1:根 1:右 0:左
if(ls == -1){
if(k == 1) return -1;
else return 1;
}
else{
if(k <= siz[ls]) return 0;
else if(k == siz[ls]+1) return -1;
else return 1;
}
}
void Push_up(int x){
siz[x] = (ls==-1?0:siz[ls])+(rs==-1?0:siz[rs])+1;
sum[x] = val[x] + (ls == -1?0:sum[ls])+ (rs == -1?0:sum[rs]);
if(ls == -1 && rs == -1){
lsum[x] = rsum[x] = msum[x] = val[x];
}
else if(ls != -1 && rs != -1){
//printf("lsum[%d] = %d %d\n",ls,lsum[ls],sum[ls]);
lsum[x] = max(lsum[ls], sum[ls] + val[x] + max(lsum[rs], 0));
rsum[x] = max(rsum[rs], sum[rs] + val[x] + max(rsum[ls], 0));
msum[x] = max( max(msum[ls], msum[rs]),val[x] + max(rsum[ls], 0) + max(lsum[rs], 0) );
}
else if(ls == -1 && rs != -1){
lsum[x] = val[x] + max( lsum[rs], 0 );
rsum[x] = max(rsum[rs], sum[rs] + val[x] );
msum[x] = max(msum[rs],val[x] + max(lsum[rs], 0) );
}
else{
lsum[x] = max(lsum[ls], sum[ls] + val[x] );
rsum[x] = val[x] + max(rsum[ls], 0);
msum[x] = max(msum[ls],val[x] + max(rsum[ls], 0));
}
}
void Rotate(int &x,int d){//d = 0:x右儿子变成跟,1:左变根
int k = s[x][d^1];s[x][d^1] = s[k][d];s[k][d] = x;
Push_up(x); Push_up(k);
x = k;
}
void Splay(int &x,int k){
int d = fd(x,k);
if(d == -1) return ;
if(d == 1) k -= (ls==-1?0:siz[ls])+1;
int p = s[x][d];
int d2 = fd(p,k),k2;
//注释以d = 0为例
if(d2 == 0) k2 = k;
else if(d2 == 1) k2 = k-(s[p][0]==-1?0:siz[ s[p][0] ])-1;
if(d2 != -1){
Splay(s[p][d2],k2);
if(d == d2) Rotate(x,1-d);
//两次方向一样,例如都是0(往左的链) 把根的第一个儿子(左边)转到根
else Rotate(s[x][d],1-d2);
//两次方向不一样 例如左右,把第一个(根的左边)的右儿子(第二个)转到跟的右侧
}
Rotate(x,1-d);//跟的左侧转到跟
}
int new_node(int vl){
s[tot][0] = s[tot][1] = -1;
siz[tot] = 1;
val[tot] = lsum[tot] = rsum[tot] = msum[tot] = sum[tot] = vl;
return tot++;
}
void Insert(int &x,int pos,int val){//for 1:ro2 1 pos pos-1
Splay(x,pos-1);
Splay(rs,pos-1-(ls==-1?0:siz[ls]));
s[rs][0] = new_node(val);
Push_up(rs);Push_up(x);
}
void pre(){
tot = 0;root = 0;
siz[tot++] = 2;siz[tot++] = 1;s[0][1] = tot-1;
s[0][0] = s[1][0] = s[1][1] = -1;
for(int i = 0 ; i <= 1; i++)
val[i] = sum[i] = lsum[i] = rsum[i] = msum[i] = 0;
}
void out(int x,int h){
if(x == -1){
return;
}
out(ls,h+1);
cout<<"|";
for(int i=0;i<h*4;i++) printf(" ");
printf("node %d: val=%d siz=%d\n",x,val[x],siz[x]);
out(rs,h+1);
}
void init(){//插到第二个上
for(int i = 1; i <= n ; i++){
scanf("%d",&p);
Insert(root,i+1,p);
}
//out(root,0);
}
void Del(int &x,int pos){
Splay(x,pos-1);
Splay(rs,pos+1-1-(ls==-1?0:siz[ls]));
//Push_up(x);
s[rs][0] = -1;
Push_up(rs);
Push_up(x);
}
void Qury(int &x,int l,int r){
Splay(x,l-1);
Splay(rs,r+1-1-(ls==-1?0:siz[ls]));
Push_up(rs);
Push_up(x);
}
void Rep(int &x,int pos,int vl){
Splay(x,pos-1);
Splay(rs,pos+1-1-(ls==-1?0:siz[ls]));
val[s[rs][0]] = sum[s[rs][0]] = lsum[s[rs][0]] = rsum[s[rs][0]] = msum[s[rs][0]] = vl;
Push_up(rs);Push_up(x);
}
char op[3];
int _pos,_add,l,r,vl;
void sov(){
scanf("%d",&m);
for(int i =1; i <= m ; i++){
scanf("%s",op);
//cout<<i<<": "<<op<<"\n";
if(op[0] == 'I'){
scanf("%d%d",&_pos,&_add);
Insert(root,_pos+1,_add);
}
if(op[0] == 'D'){
scanf("%d",&_pos);
Del(root,_pos+1);
}
if(op[0] == 'Q'){
scanf("%d%d",&l,&r);
Qury(root,l+1,r+1);
printf("%d\n",msum[ s[ s[root][1] ][ 0 ] ]);
}
if(op[0] == 'R'){
scanf("%d%d",&_pos,&vl);
Rep(root,_pos+1,vl);
}
//out(root,0);
//cout<<endl;
}
}
int main(){
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
scanf("%d",&n);
pre();
init();
//out(root);
sov();
}
/*
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
*/