splay可以支持区间操作
简单说几个需要注意的事项
1。在实现翻转的时候,切记不可以直接rev[key_value]^=1,需要调用一次update_rev(key_value),直接翻转左右孩子,首次标记的时候不能直接标记等下一次再翻转。
2。same[]懒惰标记不能记录修改的值,只记录修改与否即可,键值储存需要修改的值就可以了。因为这道题不清楚修改的值是什么~可正可负
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <math.h>
#include <vector>
#include <cstdio>
#include <string>
#include<string.h>
#include <fstream>
#include <iostream>
#include <algorithm>
using namespace std;
#define exp 1e-8
#define INF 0x3f3f3f3f
#define ll long long
#define set(a,b) memset(a,b,sizeof(a));
#define set(a,b) memset(a,b,sizeof(a));
#define for1(a,b) for(int a=1;a<=b;a++)//1---(b)
#define for0(a,b) for(int a=0;a<=b;a++)//0---(b)
void bug(string st="bug")
{cout<<st<<endl;}
template<typename __ll>
inline void READ(__ll &m){
__ll x=0,f=1;char ch=getchar();
while(!(ch>='0'&&ch<='9')){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
m=x*f;
}
template<typename __ll>
inline void read(__ll &m){READ(m);}
template<typename __ll>
inline void read(__ll &m,__ll &a){READ(m);READ(a);}
template<typename __ll>
inline void read(__ll &m,__ll &a,__ll &b){READ(m);READ(a);READ(b);}
const int MAXN=500010;
#define dat int
#define Key_value ch[ch[root][1]][0]
struct splaytree
{
int ch[MAXN][2]; //孩子
int pre[MAXN]; //父亲
int rev[MAXN]; //标志
dat key[MAXN]; //键值
int size[MAXN]; //大小
int same[MAXN];
int sum[MAXN];
int maxn[MAXN],lmaxn[MAXN],rmaxn[MAXN];
int root,tot1; //根 结点大小
int s[MAXN],tot2; //删除用的数组,记录删除了那些点,重复利用删除的点
void addnode(int &r,int father,dat k)
{
if(tot2) r=s[tot2--];
else r=++tot1;
ch[r][0]=ch[r][1]=rev[r]=0;
pre[r]=father;
key[r]=k;
size[r]=1;
same[r]=0;
sum[r]=k;
lmaxn[r]=rmaxn[r]=maxn[r]=k;
}
void push_up(int r)
{
int lson=ch[r][0],rson=ch[r][1];
size[r]=1+size[lson]+size[rson];
sum[r]=sum[lson]+sum[rson]+key[r];
lmaxn[r]=max(lmaxn[lson],sum[lson]+key[r]+max(0,lmaxn[rson]));
rmaxn[r]=max(rmaxn[rson],sum[rson]+key[r]+max(0,rmaxn[lson]));
maxn[r]=max(0,rmaxn[lson])+key[r]+max(0,lmaxn[rson]);
maxn[r]=max(maxn[r],max(maxn[lson],maxn[rson]));
}
void update_rev(int r)
{
if(!r) return ;
swap(lmaxn[r],rmaxn[r]);
swap(ch[r][0],ch[r][1]);
rev[r]^=1; //翻来翻去
}
void update_same(int r,int c)
{
if(!r) return ;
key[r]=c; //当same[r]==1 意味孩子节点都等于key[r]
sum[r]=size[r]*c;
lmaxn[r]=rmaxn[r]=maxn[r]=max(c,sum[r]);
same[r]=1;
}
void push_down(int r)
{
if(rev[r])
{
update_rev(ch[r][0]);
update_rev(ch[r][1]);
rev[r]=0;
}
if(same[r])
{
update_same(ch[r][0],key[r]);
update_same(ch[r][1],key[r]);
same[r]=0;
}
}
void build(int &x,int father,int l,int r,dat *str)
{ //当前x在调用build的时候才建立,,注意根标号是x
if(l>r) return ;
int mid=l+r>>1;
addnode(x,father,str[mid]);
build(ch[x][0],x,l,mid-1,str);
build(ch[x][1],x,mid+1,r,str);
push_up(x);
}
void init()
{
root=tot1=tot2=0;
ch[0][0]=ch[0][1]=pre[0]=size[0]=rev[0]=0;
same[0]=sum[0]=0;
maxn[0]=lmaxn[0]=rmaxn[0]=-INF;
addnode(root,0,-1); //在这里创建收尾区间,方便操作
addnode(ch[root][1],root,-1);
push_up(ch[root][1]);
push_up(root);
}
void rotate(int x,int kind)
{
int y=pre[x];
int z=pre[y];
push_down(y);
push_down(x);
ch[y][!kind]=ch[x][kind];
pre[ch[x][kind]]=y;
if(z) ch[z][ch[z][1]==y] = x;
pre[x]=pre[y];
ch[x][kind]=y;
pre[y]=x;
push_up(y);
}
void splay(int r,int goal)
{
push_down(r);
while(pre[r]!=goal) //各类push_down已经在rotate中执行
{
if(pre[pre[r]]==goal)
{
rotate(r,ch[pre[r]][0]==r);
continue;
}
int y=pre[r];
int z=pre[y];
int kind= ch[z][0]==y;
if(ch[y][kind]==r)
rotate(r,!kind),rotate(r,kind);
else rotate(y,kind),rotate(r,kind);
}
push_up(r);
if(goal==0) root=r;
}
int get_kth(int r,int k) //寻找r根子树下面的第k大
{
push_down(r);
int t=size[ch[r][0]]+1;
if(k==t) return r;
if(t>k) return get_kth(ch[r][0],k);
return get_kth(ch[r][1],k-t);
}
void select(int a,int b) //将第a个设为根,第b个设为根的右孩子
{ //根的右孩子的左孩子 代表区间[a+1,b-1]
splay(get_kth(root,a),0);
splay(get_kth(root,b),root);
}
void insert(int pos,int len,dat *str)
{
select(pos,pos+1);
build(Key_value,ch[root][1],0,len-1,str);
push_up(ch[root][1]);
push_up(root);
}
void erase(int r) //重复利用删除的结点
{
if(!r)return ;
s[++tot2]=r;
erase(ch[r][0]);
erase(ch[r][1]);
}
void Del(int pos,int len)
{
select(pos,pos+len+1);
erase(Key_value);
pre[Key_value]=0;
Key_value=0;
push_up(ch[root][1]);
push_up(root);
}
void make_same(int pos,int len,int c)
{
select(pos,pos+len+1);
update_same(Key_value,c);
push_up(ch[root][1]);
push_up(root);
}
void reverse(int pos,int len) //翻转如此就好
{
select(pos,pos+len+1);
update_rev(Key_value);
push_up(ch[root][1]);
push_up(root);
/*
select(pos,pos+len+1);
rev[key_value]^=1;
这样子写就是错误的
谨记~~~
*/
}
void get_sum(int pos,int len)
{
select(pos,pos+len+1);
printf("%d\n",sum[Key_value]);
}
void get_max()
{
select(1,size[root]);
printf("%d\n",max(maxn[Key_value],max(lmaxn[Key_value],rmaxn[Key_value])));
}
void InOrder(int r){ //中序
if(r==0)
return;
InOrder(ch[r][0]);
printf("%c",key[r]);
InOrder(ch[r][1]);
}
}t;
int str[MAXN];
int main()
{
int n,m;
int x,y,z;
char op[20];
scanf("%d %d",&n,&m);
t.init();
for(int i=0;i<n;i++)
scanf("%d",&str[i]);
t.insert(1,n,str);
while(m--)
{
scanf("%s",&op);
switch(op[2])
{
case 'S':
scanf("%d %d",&x,&y);
for(int i=0;i<y;i++)
scanf("%d",&str[i]);
t.insert(x+1,y,str);
break;
case 'L':
scanf("%d %d",&x,&y);
t.Del(x,y);
break;
case 'K':
scanf("%d %d %d",&x,&y,&z);
t.make_same(x,y,z);
break;
case 'V':
scanf("%d %d",&x,&y);
t.reverse(x,y);
break;
case 'T':
scanf("%d %d",&x,&y);
t.get_sum(x,y);
break;
case 'X':
t.get_max();
break;
}
}
}