维修数列
维修数列
题解
这是一道无旋Treap模板题,尽管笔者调了半天。
我们来分析一下每一个操作。
对于INSERT操作,我们可以将其从x分成两个子树,再将它要加的点建成一棵子树,将这三棵树合并即可。
对于DELETE操作,我们可以将其拆为三棵子树,删掉中间的子树,把两边的合并即可。
对于MAKE-SAME操作,我们可以将其三棵子树,覆盖掉中间那棵,将三棵合并即可。
对于REVERSE操作,我们还是将其分为三棵子树,翻转中间的子树,将那三棵合并。
对于GET-SUM操作,我们将其分为三棵子树,将中间的子树求和,再合并即可。
对于MAX-SUM操作,输出过程中将那棵子树求的和即可。
注意,对于翻转与覆盖,我们需用懒标记记录下当前值,不能强行暴力修改。
源码
真的很难调。
#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#define MAXN 500005
using namespace std;
typedef long long LL;
const int INF=0x7f7f7f7f;
#define gc() getchar()
int son[MAXN][2],ad[MAXN];
int val[MAXN],rnd[MAXN],cov[MAXN],siz[MAXN];
int sum[MAXN],re[MAXN],pre[MAXN],maxx[MAXN];
bool tag[MAXN];
queue<int> q;
template<typename _T>
inline void read(_T &x){
_T f=1;x=0;char s=gc();
while(s>'9'||s<'0'){if(s=='-')f=-1;s=gc();}
while(s>='0'&&s<='9'){x=(x<<3)+(x<<1)+(s^48);s=gc();}
x*=f;
}
int n,m,a[MAXN],rt,tot;
void reverse(int p){
swap(son[p][0],son[p][1]);
swap(pre[p],re[p]);
tag[p]^=1;
}
void covered(int p,int co){
cov[p]=val[p]=co;sum[p]=siz[p]*co;
maxx[p]=max(sum[p],co);
pre[p]=re[p]=max(sum[p],0);
}
void downdata(int p){
if(tag[p]){
if(son[p][0]) reverse(son[p][0]);
if(son[p][1]) reverse(son[p][1]);
tag[p]^=1;
}
if(cov[p]<INF-1){
if(son[p][0]) covered(son[p][0],cov[p]);
if(son[p][1]) covered(son[p][1],cov[p]);
cov[p]=INF;
}
}
void updata(int x){
if(!x)return ;
siz[x]=siz[son[x][0]]+siz[son[x][1]]+1;
sum[x]=sum[son[x][0]]+sum[son[x][1]]+val[x];
maxx[x]=max(max(0,re[son[x][0]])+val[x]+max(0,pre[son[x][1]]),max(maxx[son[x][0]],maxx[son[x][1]]));
pre[x]=max(pre[son[x][0]],sum[son[x][0]]+val[x]+max(0,pre[son[x][1]]));
re[x]=max(re[son[x][1]],sum[son[x][1]]+val[x]+max(0,re[son[x][0]]));
}
int newnode(int v){
int x;
if(q.empty()) x=++tot;
else x=q.front(),q.pop();
siz[x]=1;cov[x]=INF;rnd[x]=rand();
sum[x]=pre[x]=re[x]=maxx[x]=val[x]=v;
tag[x]=son[x][0]=son[x][1]=0;
return x;
}
void build(int &p,int l,int r){
if(l>r) return ;
int mid=(l+r)>>1;p=newnode(ad[mid]);
build(son[p][0],l,mid-1);
build(son[p][1],mid+1,r);
updata(p);
}
int merge(int a,int b){
if(!a||!b) return a+b;
downdata(a);downdata(b);
if(rnd[a]<rnd[b]){
son[a][1]=merge(son[a][1],b);
updata(a);return a;
}
son[b][0]=merge(a,son[b][0]);
updata(b);return b;
}
void split(int now,int k,int &x,int &y){
if(!now){
x=y=0;
return ;
}
downdata(now);
if(k<=siz[son[now][0]])
y=now,split(son[now][0],k,x,son[now][0]);
else x=now,split(son[now][1],k-siz[son[now][0]]-1,son[now][1],y);
updata(now);
}
void rudui(int x){
if(!x) return ;
q.push(x);
rudui(son[x][0]);rudui(son[x][1]);
}
signed main()
{
read(n);read(m);
for(int i=1;i<=n;i++) read(ad[i]);
cov[rt]=INF;maxx[rt]=-INF;build(rt,1,n);
for(int i=1;i<=m;i++)
{
char opt[15];scanf("%s",opt);
if(opt[0]=='I'){
int pos,tot;read(pos);read(tot);
for(int i=1;i<=tot;i++) read(ad[i]);
int x,y,z;build(z,1,tot);split(rt,pos,x,y);
rt=merge(merge(x,z),y);
}
if(opt[0]=='D'){
int pos,tot;read(pos);read(tot);
int xa,ya,xb,yb;split(rt,pos-1,xa,ya);split(ya,tot,xb,yb);
rt=merge(xa,yb);rudui(xb);
}
if(opt[0]=='M'&&opt[5]=='S'){
int pos,tot,c;read(pos);read(tot);read(c);
int xa,ya,xb,yb;split(rt,pos-1,xa,ya);split(ya,tot,xb,yb);
covered(xb,c);rt=merge(xa,merge(xb,yb));
}
if(opt[0]=='R'){
int pos,tot;read(pos);read(tot);
int xa,xb,ya,yb;split(rt,pos-1,xa,ya);split(ya,tot,xb,yb);
reverse(xb);rt=merge(merge(xa,xb),yb);
}
if(opt[0]=='G'){
int pos,tot;read(pos);read(tot);
int xa,ya,xb,yb;split(rt,pos-1,xa,ya);split(ya,tot,xb,yb);
printf("%d\n",sum[xb]);rt=merge(xa,merge(xb,yb));
}
if(opt[0]=='M'&&opt[4]=='S') printf("%d\n",maxx[rt]);
}
return 0;
}

浙公网安备 33010602011771号