不得不说这题目真的猥琐,写一个小时调一晚上加一上午,还被卡常了。
这里不放题解,主要来总结一下Splay区间修改比较猥琐的地方。
一 、查找第k大的时候一定要记得push_down;
二、有改值标记的题目push_down一定要写成改值的push_down,今天我才知道我以前写的线段树都是jg,全是错的标记方式。
三、注意一下边界问题和Splay函数里的push_down和update操作。
四、注意update的常数…
代码
#include<ctime>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<string>
#include<cassert>
#include<cmath>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<climits>
#define X first
#define Y second
#define DB double
#define MP make_pair
#define LL long long
#define pb push_back
#define sqr(_) ((_)*(_))
#define INF 0x3f3f3f3f
#define pii pair<int,int>
#define pdd pair<DB,DB>
#define ull unsigned LL
#define lc son[now][0]
#define rc son[now][1]
#define DEBUG(...) fprintf(stderr,__VA_ARGS__)
const int MAXN=600010;
int n,m,st[MAXN],top=0,a[MAXN];
char s[20]={};
void Read(int& x)
{
x=0;int flag=0,sgn=1;char c;
while(c=getchar())
{
if(c=='-')sgn=-1;
else if(c>='0'&&c<='9')x*=10,x+=c-'0',flag=1;
else if(flag)break;
}
x*=sgn;
}
inline int max(int x,int y)
{
return x>y?x:y;
}
struct splay_Tree{
int size[MAXN],v[MAXN],sum[MAXN],lm[MAXN],mx[MAXN],rm[MAXN];
int son[MAXN][2],root,cnt,fa[MAXN],rev[MAXN],cov[MAXN];
splay_Tree()
{
root=cnt=0;
memset(fa,0,sizeof(fa));
memset(cov,INF,sizeof(cov));
memset(size,0,sizeof(size));
memset(sum,0,sizeof(sum));
memset(son,0,sizeof(son));
memset(lm,-INF,sizeof(lm));
memset(mx,-INF,sizeof(mx));
memset(rm,-INF,sizeof(rm));
fa[2]=1;son[1][1]=2;root=1;
lm[1]=rm[1]=mx[1]=lm[2]=mx[2]=rm[2]=0;
lm[0]=mx[0]=rm[0]=-INF;
size[2]=1;size[1]=2;
}
int build(int b,int val,int d)
{
int New=st[top];top--;
fa[New]=b;
son[b][d]=New;
cov[New]=INF;
rev[New]=son[New][0]=son[New][1]=0;
v[New]=sum[New]=mx[New]=lm[New]=rm[New]=val;
size[New]=1;
return New;
}
void update(int now)
{
if(!now)return;
size[now]=size[lc]+size[rc]+1;
sum[now]=sum[lc]+sum[rc]+v[now];
mx[now] = max(0,rm[lc])+v[now]+max(0,lm[rc]);
mx[now] = max(mx[now],max(mx[lc],mx[rc]));
lm[now] = max(lm[lc],sum[lc]+v[now]+max(0,lm[rc]));
rm[now] = max(rm[rc],sum[rc]+v[now]+max(0,rm[lc]));
}
void update_same(int now,int c)
{
if(!now)return;
cov[now]=c;
v[now]=c;
sum[now]=size[now]*c;
mx[now]=max(sum[now],c);
lm[now]=max(sum[now],c);
rm[now]=max(sum[now],c);
}
void update_rev(int now)
{
if(!now)return;
rev[now]^=1;
std::swap(lc,rc);
std::swap(lm[now],rm[now]);
}
void push_down(int now)
{
if(!now)return;
if(rev[now])
{
update_rev(lc);
update_rev(rc);
rev[now]=0;
}
if(cov[now]!=INF)
{
update_same(son[now][0],cov[now]);
update_same(son[now][1],cov[now]);
cov[now]=INF;
}
}
void rotate(int x)
{
int y=fa[x],d=son[y][1]==x?1:0;
push_down(y);
push_down(x);
if(fa[y])
son[fa[y]][son[fa[y]][1]==y]=x;
fa[x]=fa[y];
fa[y]=x;
if(son[x][d^1])
fa[son[x][d^1]]=y;
son[y][d]=son[x][d^1];
son[x][d^1]=y;
update(y);
}
void splay(int x,int f)
{
push_down(x);
while(fa[x]!=f)
{
int y=fa[x];
if(fa[y]==f)
{
rotate(x);
break;
}
if((son[fa[y]][1]==y)^(son[y][1]==x))
{
rotate(x);
rotate(x);
}
else
{
rotate(y);
rotate(x);
}
}
if(f==0)
root=x;
update(x);
}
int find(int now,int k)
{
push_down(now);
if(size[lc]+1>k)
find(lc,k);
else if(size[lc]+1==k)
return now;
else
find(rc,k-size[lc]-1);
}
void Insert(int now,int val)
{
int a=find(root,now+1),
b=find(root,now+2);
splay(a,0);
splay(b,root);
build(b,val,0);
update(b);
update(a);
}
void recy(int now)
{
if(!now)return;
st[++top]=(now);
recy(lc);
recy(rc);
}
void del(int now,int tot)
{
int a=find(root,now),
b=find(root,now+tot+1);
splay(a,0);
splay(b,root);
int s=son[b][0];
fa[s]=0;son[b][0]=0;
recy(s);
}
void mod(int now,int tot,int c)
{
int a=find(root,now),
b=find(root,now+tot+1);
splay(a,0);
splay(b,root);
update_same(son[b][0],c);
update(b);
update(a);
}
void Rev(int now,int tot)
{
int a=find(root,now),
b=find(root,now+tot+1);
splay(a,0);
splay(b,root);
update_rev(son[b][0]);
update(b);
update(a);
}
void Sum(int now,int tot)
{
//assert(now!=0);
int a=find(root,now),
b=find(root,now+tot+1);
//DEBUG("%d\n",mx[root]);
splay(a,0);
//DEBUG("%d\n",mx[root]);
splay(b,root);
//DEBUG("%d\n",mx[root]);
printf("%d\n",sum[son[b][0]]);
}
void Max()
{
splay(1,0);
splay(2,1);
printf("%d\n",mx[son[2][0]]);
}
void init(int l,int r,int f,int d)
{
if(l>r)return;
int mid=(l+r)>>1;
int now=build(f,a[mid],d);
init(l,mid-1,now,0);
init(mid+1,r,now,1);
update(now);
}
}T;
int main()
{
#ifndef ONLINE_JUDGE
freopen("mend.in","r",stdin);
freopen("mend.out","w",stdout);
#endif
std::cin>>n>>m;
for(int i=600000;i>=1;i--)
st[++top]=i;
top-=2;
int tot=0;
for(int i=1;i<=n;i++)
{
Read(a[i]);
}
T.init(1,n,2,0);
for(int i=1;i<=m;i++)
{
scanf("%s",s);
//DEBUG("%d %s\n",i,s);
if(s[0]=='G')
{
int a,b;
Read(a);Read(b);
T.Sum(a,b);
}
else if(s[0]=='M'&&s[2]=='X')
T.Max();
else if(s[0]=='I')
{
tot=0;
int a,b,c;
Read(a);Read(b);
for(int i=1;i<=b;i++)
{
Read(c);
T.Insert(a+tot,c);
tot++;
}
}
else if(s[2]=='K')
{
int a,b,c;
Read(a);Read(b);Read(c);
T.mod(a,b,c);
}
else if(s[0]=='R')
{
int a,b;
Read(a);Read(b);
T.Rev(a,b);
}
else
{
int a,b;
Read(a);Read(b);
T.del(a,b);
}
}
}