P4146 序列终结者(Splay树)
给出一个初始为0的序列。
询问区间最大值,并同时支持区间修改和区间翻转。
就正常模仿线段树,给Splay打懒标记即可。
巨大的坑就是要保证虚拟节点,0,1,n+2不对答案产生影响。
这里把他们的权值和区间值全置为负无穷。
//区间修改
//区间反转
//区间求MAX
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+10;
const long long inf=1e18;
int rt,fa[maxn],ch[maxn][2],sz[maxn];
int lz[maxn];//区间翻转标记
long long add_lz[maxn];//区间修改标记
long long c[maxn];//保存区间最大值
long long w[maxn];
int tot;
long long a[maxn];
struct Splay {
void maintain (int x) {
sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+1;
c[x]=max(w[x],max(c[ch[x][0]],c[ch[x][1]]));
}
void pushdown (int x) {
if (!x) return;
if (lz[x]) {
swap(ch[x][0],ch[x][1]);
lz[ch[x][0]]^=lz[x];
lz[ch[x][1]]^=lz[x];
lz[x]=0;
}
if (add_lz[x]) {
if (ch[x][0]){
c[ch[x][0]]+=add_lz[x];
w[ch[x][0]]+=add_lz[x];
add_lz[ch[x][0]]+=add_lz[x];
}
if (ch[x][1]){
c[ch[x][1]]+=add_lz[x];
w[ch[x][1]]+=add_lz[x];
add_lz[ch[x][1]]+=add_lz[x];
}
add_lz[x]=0;
}
}
bool get (int x) {
return x==ch[fa[x]][1];
}
void rotate (int x) {
pushdown(x);
pushdown(fa[x]);
int y=fa[x];
int z=fa[y];
int chk=get(x);
ch[y][chk]=ch[x][chk^1];
if (ch[x][chk^1]) {
fa[ch[x][chk^1]]=y;
}
ch[x][chk^1]=y;
fa[y]=x;
fa[x]=z;
if (z) {
ch[z][y==ch[z][1]]=x;
}
maintain(x);
maintain(y);
}
void splay (int x,int ed) {
for (int f=fa[x];(f=fa[x])!=ed;rotate(x)) {
if (fa[f]!=ed) {
rotate(get(x)==get(f)?f:x);
}
}
if (ed==0) rt=x;
}
int build (int l,int r,int f) {
if (l>r) return 0;
int mid=(l+r)>>1;
int u=++tot;
fa[u]=f;
ch[u][0]=ch[u][1]=lz[u]=0;
sz[u]=1;
ch[u][0]=build(l,mid-1,u);
ch[u][1]=build(mid+1,r,u);
maintain(u);
return u;
}
int rk (int x) {
int cur=rt;
while (1) {
pushdown(cur);
if (x<=sz[ch[cur][0]]) {
cur=ch[cur][0];
}
else {
x-=sz[ch[cur][0]]+1;
if (!x) return cur;
cur=ch[cur][1];
}
}
return 0;
}
void rev (int x,int y) {
int l=x-1;
int r=y+1;
l=rk(l);
r=rk(r);
splay(l,0);
splay(r,l);
int pos=ch[rt][1];
pos=ch[pos][0];
lz[pos]^=1;
}
void up (int x,int y,int v) {
int l=x-1;
int r=y+1;
l=rk(l);
r=rk(r);
splay(l,0);
splay(r,l);
int pos=ch[rt][1];
pos=ch[pos][0];
c[pos]+=v;
w[pos]+=v;
add_lz[pos]+=v;
}
long long query (int x,int y) {
int l=x-1;
int r=y+1;
l=rk(l);
r=rk(r);
splay(l,0);
splay(r,l);
int pos=ch[rt][1];
pos=ch[pos][0];
return c[pos];
}
}splay;
int main () {
int n,m;
scanf("%d%d",&n,&m);
c[0]=w[0]=w[1]=w[n+2]=-inf;
rt=splay.build(1,n+2,0);
while (m--) {
int op;
scanf("%d",&op);
if (op==1) {
int l,r,v;
scanf("%d%d%d",&l,&r,&v);
l++,r++;
splay.up(l,r,v);
}
else if (op==2){
int l,r;
scanf("%d%d",&l,&r);
l++,r++;
splay.rev(l,r);
}
else {
int l,r;
scanf("%d%d",&l,&r);
l++,r++;
long long ans=splay.query(l,r);
printf("%lld\n",ans);
}
}
}