维修数列

维修数列

题解

这是一道无旋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;
}

谢谢!!!

posted @ 2019-12-25 14:14  StaroForgin  阅读(7)  评论(0)    收藏  举报  来源