| 
	
	
		
			参考论文《运用伸展树解决数列维护问题》   /**//* 
  题意:实现插入、删除、查询最大子段和、求和 
  翻转,置为一样 
  
  每次修改后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; 
  }     
	    
    
 |