参考论文《运用伸展树解决数列维护问题》
/*
    题意:实现插入、删除、查询最大子段和、求和
           翻转,置为一样

   每次修改后splay到根(这样来更新)
   update操作里面需要有push_down先
   每次访问节点时都需要push_down
*/

#include
<cstdio>
#include
<cstring>
#include
<algorithm>
using namespace std;

const int MAXN = 500000*2;
const int INF = 1000000000;

inline 
int max(int a,int b){return a>b?a:b;}
inline 
int min(int a,int b){return a<b?a:b;}

struct Node
{
    
int ml,mc,mr;
    
int size,sum,val;
    
bool rev,same;
    Node 
*ch[2],*pre;
}
;

struct Splay
{
    Node 
*root,*null;
    Node data[MAXN],
*Store[MAXN];
    
int top,cnt;

    Node 
*newNode(int val)
    
{
        Node 
*p;
        
if(top)p=Store[top--];
        
else p=&data[cnt++];
        p
->sum=p->val=val;
        p
->ml=p->mc=p->mr=val;
        p
->size=1;
        p
->ch[0]=p->ch[1]=p->pre=null;
        p
->rev=p->same=false;
        
return p;
    }

    
void init()
    
{
        top
=cnt=0;
        
null = newNode(-INF);
        
null->size=null->sum=0;
        root
=newNode(-INF);
        root
->ch[1]=newNode(-INF);
        root
->ch[1]->pre=root;
        update(root);
    }

    
void update(Node *p)
    
{
        
if(p==null)return;
        
//需要先push_down
        push_down(p);
        push_down(p
->ch[0]);
        push_down(p
->ch[1]);

        p
->size=p->ch[0]->size+p->ch[1]->size+1;
        p
->sum=p->ch[0]->sum+p->ch[1]->sum+p->val;

        p
->ml=max(p->ch[0]->ml,p->ch[0]->sum+p->val+max(0,p->ch[1]->ml));
        p
->mr=max(p->ch[1]->mr,p->ch[1]->sum+p->val+max(0,p->ch[0]->mr));

        p
->mc=max(p->ch[0]->mc,p->ch[1]->mc);
        p
->mc=max(p->mc,max(p->ch[0]->mr+p->ch[1]->ml,0)+p->val);
        p
->mc=max(p->mc,max(p->ch[0]->mr,p->ch[1]->ml)+p->val);
    }

    
void push_down(Node *p)
    
{
        
if(p==null)return;
        
if(p->rev)
        
{
            p
->rev=false;
            p
->ch[0]->rev^=1;
            p
->ch[1]->rev^=1;
            swap(p
->ch[0],p->ch[1]);
            swap(p
->ml,p->mr);
        }

        
if(p->same)
        
{
            p
->same=false;
            p
->ch[0]->same=p->ch[1]->same=true;
            p
->ch[0]->val=p->ch[1]->val=p->val;
            p
->sum=p->val*p->size;
            p
->ml=p->mc=p->mr=p->val*p->size;
            
if(p->val<0)
                p
->ml=p->mc=p->mr=p->val;
        }

    }

    
void rotate(Node *x,int c)
    
{
        Node 
*y=x->pre;
        push_down(y);
        push_down(x);
        y
->ch[!c]=x->ch[c];
        
if(x->ch[c]!=null)x->ch[c]->pre=y;
        x
->pre=y->pre;
        
if(y->pre!=null)
        
{
            
if(y->pre->ch[0]==y)y->pre->ch[0]=x;
            
else y->pre->ch[1]=x;
        }

        x
->ch[c]=y;
        y
->pre=x;
        update(y);
        
if(y==root)root=x;
    }

    
void splay(Node *x,Node *f)
    
{
        
if(x==null)return;
        
for(push_down(x);x->pre!=f;)
        
{
            
if(x->pre->pre==f)
            
{
                
if(x->pre->ch[0]==x)rotate(x,1);
                
else rotate(x,0);
            }

            
else
            
{
                Node 
*y=x->pre,*z=y->pre;
                
if(z->ch[0]==y)
                
{
                    
if(y->ch[0]==x)rotate(y,1),rotate(x,1);
                    
else rotate(x,0),rotate(x,1);
                }

                
else 
                
{    
                    
if(y->ch[1]==x)rotate(y,0),rotate(x,0);
                    
else rotate(x,1),rotate(x,0);
                }
    
            }

        }

        update(x);
    }

    
void select(int k,Node *f)
    
{
        Node 
*t;
        
for(t=root;;)
        
{
            push_down(t);
            
int size=t->ch[0]->size;
            
if(k==size)break;
            
if(k<size)t=t->ch[0];
            
else k-=size+1,t=t->ch[1];
        }

        splay(t,f);
    }

    Node 
*build(int left,int right,int *ary)        
    
{
        
if(left>right)return null;
        
int mid=(left+right)>>1;
        Node 
*p=newNode(ary[mid]);
        p
->ch[0]=build(left,mid-1,ary);
        
if(p->ch[0]!=null)p->ch[0]->pre=p;
        p
->ch[1]=build(mid+1,right,ary);
        
if(p->ch[1]!=null)p->ch[1]->pre=p;
        update(p);
        
return p;
    }

    
void insert(int pos,int *ary,int n)
    
{
        select(pos
-1,null);
        select(pos,root);
        Node 
*p=build(0,n-1,ary);
        root
->ch[1]->ch[0]=p;
        p
->pre=root->ch[1];
        splay(p,
null);
    }

    
void del(int start,int end)//[start,end)
    {
        select(start
-1,null);
        select(end,root);
        Node 
*p=root->ch[1]->ch[0];
        root
->ch[1]->ch[0]=null;
        splay(root
->ch[1],null);
        recyle(p);
//
    }

    
void recyle(Node *p)
    
{
        
if(p==null)return;
        recyle(p
->ch[0]);
        recyle(p
->ch[1]);
        Store[
++top]=p;
    }

    
int getSum(int start,int end)//[start,end)
    {
        select(start
-1,null);
        select(end,root);
        
return root->ch[1]->ch[0]->sum;
    }

    
int maxSum(int start,int end)
    
{
        select(start
-1,null);
        select(end,root);
        
return root->ch[1]->ch[0]->mc;
    }

    
void makeSame(int start,int end,int c)
    
{
        select(start
-1,null);
        select(end,root);
        Node 
*p=root->ch[1]->ch[0];
        p
->same=true;
        p
->val=c;
        splay(p,
null);
    }

    
void reverse(int start,int end)
    
{
        select(start
-1,null);
        select(end,root);
        Node 
*p=root->ch[1]->ch[0];
        p
->rev^=1;
        splay(p,
null);
    }

    
void print(Node *p)
    
{
        
if(p==null)return;
        push_down(p);
        print(p
->ch[0]);
        printf(
"%d %d %d %d %d\n",p->val,p->ml,p->mc,p->mr,p->mc);
        print(p
->ch[1]);        
    }

}
splay;

int ary[MAXN];

int main()
{
    
//freopen("in","r",stdin);
    int T;
    
for(scanf("%d",&T);T--;)
    
{
        
int N,Q,n,x,y;
        
char cmd[20];
        scanf(
"%d%d",&N,&Q);
        
for(int i=0;i<N;i++)
            scanf(
"%d",&ary[i]);
        splay.init();
        splay.insert(
1,ary,N);
        
for(;Q--;)
        
{
            scanf(
"%s",cmd);
            
if(strcmp(cmd,"GET-SUM")==0)
            
{
                scanf(
"%d%d",&x,&n);
                printf(
"%d\n",splay.getSum(x,x+n));
            }

            
if(strcmp(cmd,"MAX-SUM")==0)
            
{
                printf(
"%d\n",splay.maxSum(1,splay.root->size-1));
            }

            
if(strcmp(cmd,"INSERT")==0)
            
{
                scanf(
"%d%d",&x,&n);
                x
++;
                
for(int i=0;i<n;i++)
                    scanf(
"%d",&ary[i]);
                splay.insert(x,ary,n);
            }

            
if(strcmp(cmd,"DELETE")==0)
            
{
                scanf(
"%d%d",&x,&n);
                splay.del(x,x
+n);
            }

            
if(strcmp(cmd,"REVERSE")==0)
            
{
                scanf(
"%d%d",&x,&n);
                splay.reverse(x,x
+n);
            }

            
if(strcmp(cmd,"MAKE-SAME")==0)
            
{
                scanf(
"%d%d%d",&x,&n,&y);
                splay.makeSame(x,x
+n,y);
            }

        }

    }

    
return 0;
}