//#include<bits/stdc++.h>
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<stdio.h>
#include<algorithm>
#include<queue>
#include<string.h>
#include<iostream>
#include<math.h>
#include<set>
#include<map>
#include<vector>
#include<iomanip>
#include<bitset>
using namespace std; //
#define ll long long
#define pb push_back
#define FOR(a) for(int i=1;i<=a;i++)
#define sqr(a) (a)*(a)
#define dis(a,b) sqrt(sqr(a.x-b.x)+sqr(a.y-b.y))
ll qp(ll a,ll b,ll mod){
ll t=1;while(b){if(b&1)t=t*a%mod;b>>=1;a=a*a%mod;}return t;
}
struct DOT{int x;int y;};
const int dx[4]={0,0,-1,1};
const int dy[4]={1,-1,0,0};
const int inf=0x3f3f3f3f;
const ll mod=1e9+7;
const int maxn=5e5+6;
int n,m;
int a[maxn];
int rt=0;
int c[maxn][2],parent[maxn];
int val[maxn],size[maxn];
int lx[maxn],rx[maxn],mx[maxn],sum[maxn];
int tag[maxn],rev[maxn];
int id[maxn];
queue<int>Q;
inline void pushup(int x){
int l=c[x][0],r=c[x][1];
size[x]=size[l]+size[r]+1; //子树大小
sum[x]=sum[l]+sum[r]+val[x]; //区间和
mx[x]=max(max(mx[r],mx[l]),val[x]+rx[l]+lx[r]); //最大子段和
lx[x]=max(lx[l],sum[l]+val[x]+lx[r]); //最大前缀
rx[x]=max(rx[r],sum[r]+val[x]+rx[l]); //最大后缀
}
void pushdown(int x){
int l=c[x][0],r=c[x][1];
if(tag[x]){
tag[x]=rev[x]=0;
if(l)tag[l]=1,val[l]=val[x],sum[l]=val[x]*size[l];
if(r)tag[r]=1,val[r]=val[x],sum[r]=val[x]*size[r];
if(val[x]>=0){
if(l)lx[l]=rx[l]=mx[l]=sum[l];
if(r)lx[r]=rx[r]=mx[r]=sum[r];
}else{
if(l)lx[l]=rx[l]=0;mx[l]=val[x];
if(r)lx[r]=rx[r]=0,mx[r]=val[x];
}
}
if(rev[x]){
rev[x]=0;rev[l]^=1;rev[r]^=1;
swap(lx[l],rx[l]);swap(lx[r],rx[r]);
swap(c[l][0],c[l][1]);swap(c[r][0],c[r][1]);
}
}
void rotate(int x,int &k){
int y=parent[x],z=parent[y],d=c[y][1]==x;
if(y==k)k=x;else c[z][c[z][1]==y]=x;parent[x]=z;
c[y][d]=c[x][d^1];parent[c[x][d^1]]=y;
c[x][d^1]=y;parent[y]=x;
pushup(y);pushup(x);
}
void splay(int x,int &k){
while(x!=k){
int y=parent[x],z=parent[y];
if(y!=k) (c[y][0]==x^c[z][0]==y)?rotate(x,k):rotate(y,k);
rotate(x,k);
}
}
inline int find(int x,int k){
pushdown(x);
int lc=c[x][0],rc=c[x][1];
if(k>size[lc]+1)return find(rc,k-size[lc]-1);
else if(k<=size[lc])return find(lc,k);
else return x;
}
inline int Split(int l,int r){
int x=find(rt,l);
int y=find(rt,r);
splay(x,rt);splay(y,c[x][1]);
return c[y][0];
}
void init(){for(int i=n+3;i<maxn;i++)Q.push(i);}
inline void recycle(int x){
int &l=c[x][0],&r=c[x][1];
if(l)recycle(l);if(r)recycle(r);
Q.push(x);
parent[x]=l=r=tag[x]=rev[x]=0;
}
void erase(int l,int r){
int x=Split(l,r),y=parent[x];
recycle(x);
c[y][0]=0;pushup(y);pushup(parent[y]);
}
void build(int l,int r,int f){
if(l>r)return;
int m=l+r>>1,now=id[m],pa=id[f];
val[now]=a[m];parent[now]=pa;
c[pa][m>=f]=now;
if(l==r){
mx[now]=sum[now]=val[now];
lx[now]=rx[now]=max(0,val[now]);
size[now]=1;
return;
}
build(l,m-1,m);build(m+1,r,m);
pushup(now);
}
void insert(int l,int tot){
for(int i=1;i<=tot;i++)scanf("%d",&a[i]);
for(int i=1;i<=tot;i++)id[i]=Q.front(),Q.pop();
build(1,tot,0);
int z=id[1+tot>>1],x=find(rt,l+1),y=find(rt,l+2); //标号右移
splay(x,rt);splay(y,c[x][1]);
parent[z]=y;c[y][0]=z;
pushup(y);pushup(x);
}
int query(int l,int r){
int x=Split(l,r);
return sum[x];
}
void rever(int l,int r){
int x=Split(l,r),y=parent[x];
if(!tag[x]){
rev[x]^=1;
swap(c[x][0],c[x][1]);
swap(lx[x],rx[x]);
pushup(y);pushup(parent[y]);
}
}
void update(int l,int r,int v){
int x=Split(l,r),y=parent[x];
val[x]=v;tag[x]=1;sum[x]=size[x]*v;
if(v>=0)lx[x]=rx[x]=mx[x]=sum[x];
else lx[x]=rx[x]=0,mx[x]=v;
pushup(y);pushup(parent[y]);
}
char s[20];
int main(){
scanf("%d%d",&n,&m);
mx[0]=a[1]=a[n+2]=-inf;
for(int i=1;i<=n;i++){
scanf("%d",&a[i+1]);
}
for(int i=1;i<=n+2;i++)id[i]=i;
init();
build(1,n+2,0);rt=n+3>>1;
for(int i=1;i<=m;i++){
scanf("%s",s);
if(s[2]=='X')printf("%d\n",mx[rt]);
else{
int k,tot;scanf("%d",&k);scanf("%d",&tot);
if(s[2]=='S')insert(k,tot);
if(s[2]=='L')erase(k,k+tot+1);
if(s[2]=='K'){int x;scanf("%d",&x);update(k,k+tot+1,x);}
if(s[2]=='V')rever(k,k+tot+1);
if(s[2]=='T')printf("%d\n",query(k,k+tot+1));
}
}
}
通过split提取目标区间,由于旋转到根影响的父节点就2个
支持O(logn)区间反转,O(元素个数)加入元素
回收节点编号的操作挺棒的,以后不用担心数组版数据结构溢编号了