好久没训练了今天手感都没了就打了一道题
但是还没有调节出来,而且还没有写完,题目有好多个要求明天继续写继续调试
//维护序列
#include<bits/stdc++.h>
using namespace std;
#define debug cout<<" debug: "
typedef long long ll;
const int N=4e6+40;
const int inf=1e9;//用于区分你的flag标志因为有可能全部都设置为0那样的话就不太好判断了
struct node{
int s[2],p,v,sz,g;
ll ls,rs,sum,tsum;//表示的是最大的连续字串和
int flag,tag;
void init(int p_,int v_,int c){
p=p_,v=v_,sz=1,g=c;
flag=inf,tsum=ls=rs=sum=v;
tag=0;
}
}t[N];
int root,idx=1,rt,w[N];//一个是需要的添加的序列的新的根一个是原本的根
void push_up(int u){
auto s=t[u].s;
t[u].sz=t[s[0]].sz+t[s[1]].sz+1;
t[u].sum=t[u].v+t[s[0]].sum+t[s[1]].sum;
t[u].ls=max(t[s[0]].ls,max(t[s[0]].sum+t[u].v,t[s[0]].sum+t[u].v+t[s[1]].ls));
t[u].rs=max(t[s[1]].rs,max(t[s[1]].sum+t[u].v,t[s[1]].sum+t[u].v+t[s[0]].rs));
t[u].tsum=max(max((ll)t[u].v,t[u].v+t[s[0]].rs+t[s[1]].ls),max(t[u].v+t[s[1]].ls,t[u].v+t[s[0]].rs));//中间贯穿的部分
t[u].tsum=max(max(t[s[0]].tsum,t[s[1]].tsum),max(t[u].ls,t[u].rs));
}
void push_down(int u){
if(t[u].flag<inf){
auto s=t[u].s;
t[s[0]].v=t[s[1]].v=t[u].flag;
t[s[0]].sum=(ll)t[s[0]].sz*t[s[0]].flag;
t[s[1]].sum=(ll)t[s[1]].sz*t[s[1]].flag;
if(t[u].flag>=0){
t[s[0]].ls=t[s[0]].rs=t[s[0]].tsum=t[s[0]].sum;
t[s[1]].ls=t[s[1]].rs=t[s[1]].tsum=t[s[1]].sum;
}else {
t[s[0]].ls=t[s[0]].rs=t[s[1]].ls=t[s[1]].rs=t[s[0]].tsum=t[s[1]].tsum=t[u].flag;
}
t[s[0]].flag=t[s[1]].flag=t[u].flag;
t[u].flag=inf;//清除标志
if(t[u].tag){
swap(t[u].s[0],t[u].s[1]);
t[s[0]].tag^=1;
if(t[s[0]].tag){
swap(t[s[0]].ls,t[s[0]].rs);
}
t[s[1]].tag^=1;
if(t[s[1]].tag){
swap(t[s[1]].ls,t[s[1]].rs);
}
t[u].tag=0;
}//需要进行一个交换
}
}
void rotate(int x){
int y=t[x].p,z=t[y].p;
int k=(t[y].s[1]==x);
t[z].s[t[z].s[1]==y]=x,t[x].p=z;
t[y].s[k]=t[x].s[k^1],t[t[x].s[k^1]].p=y;
t[x].s[k^1]=y,t[y].p=x;
push_up(y),push_up(x);
}
void splay(int x,int k){
while(t[x].p!=k){
int y=t[x].p,z=t[y].p;
if(z!=k){
if((t[z].s[1]==y)^(t[y].s[1]==x)){
rotate(x);
}else rotate(y);
}
rotate(x);
}
if(!k){
root=x;
}
if(k==1){
rt=x;
}
}
void insert(int k,int i){
int u=root,p=0;
while(u){
p=u;
t[u].sz++;
t[u].sum+=k;//这个才是具体的权值需要在这里就把他给更新了
u=t[u].s[i>t[u].g];
}
u=++idx;
t[u].init(p,k,i);
if(p){
t[p].s[i>t[p].g]=u;
}
splay(u,0);//作为根搞起来
}
int l,r;
void init(){
t[rt=l=++idx].init(1,-inf,0);
t[r=++idx].init(l,inf,0);
t[l].s[1]=r;//这个也是一个关系
push_up(l);//记得需要进行传递啊
}
void build(int n){
for(int i=1;i<=n;i++){
insert(w[i],i);
}
}
int get_k(int u,int k){
push_down(u);
int l=t[u].s[0];
if(t[l].sz>=k) return get_k(l,k);
if(t[l].sz+1==k) return u;//返回的是你的编号
return get_k(t[u].s[1],k-t[l].sz-1);//记得这里不需要sum的总和
}
int main(){
int n,m;
scanf("%d%d",&n,&m);
init();
for(int i=1;i<=n;i++){
scanf("%d",&w[i]);
}
build(n);//建立完了之后的话
t[r].s[0]=root;
t[root].p=r;
push_up(r),push_up(l);//他变化了之后的话,l也是会变化的
char a[10];
for(int i=1;i<=m;i++){
int tot,x,l,r,y;
scanf("%s",a);
if(a[0]=='I'){
scanf("%d%d",&x,&tot);
for(int i=1;i<=tot;i++){
scanf("%d",&w[i]);
}
root=0;
t[root].s[0]=t[root].s[1]=0;//清零
build(tot);
int l=get_k(rt,x+1),r=get_k(rt,x+2);
splay(l,1),splay(r,l);//真实的树是以rt为1开始进行的
t[r].s[0]=root;
t[root].p=r;
push_up(r),push_up(l);//记得更新
}else if(a[0]=='D'){
scanf("%d%d",&x,&tot);
int l=get_k(rt,x),r=get_k(rt,x+tot+1);//这个的话是包括这个本身的点的啊
splay(l,1),splay(r,l);
t[r].s[0]=0;
push_up(r),push_up(l);
}else if(a[2]=='K'){
scanf("%d%d%d",&x,&tot,&y);
int l=get_k(rt,x),r=get_k(rt,x+tot+1);
splay(l,1),splay(r,l);
//这个的话是需要进行的修改标志
auto g=t[r].s[0];
t[g].v=t[g].flag=y;
t[g].sum=(ll)t[g].sz*t[g].v;
if(y>=0){
t[g].ls=t[g].rs=t[g].tsum=t[g].sum;
}else {
t[g].ls=t[g].rs=t[g].tsum=y;
}
push_up(r),push_up(l);
}else if(a[0]=='R'){
scanf("%d%d",&x,&tot);
int l=get_k(rt,x),r=get_k(rt,x+tot+1);
splay(l,1),splay(r,l);
auto g=t[r].s[0];
t[g].tag^=1;
swap(t[g].ls,t[g].rs);
push_up(r),push_up(l);
}//这个的话就是交换了啊
else if(a[0]=='G'){
scanf("%d%d",&x,&tot);
int l=get_k(rt,x),r=get_k(rt,x+tot+1);
splay(l,1),splay(r,l);
auto g=t[r].s[0];
printf("%lld\n",t[g].sum);
}//直接获得答案的话还是有点不太确定的啊
else {
ll res=t[rt].tsum;
printf("%lld\n",(res>inf)?res-inf:res);
}
}
return 0;
}