BZOJ1500 [NOI2005]维修数列 splay

原文链接http://www.cnblogs.com/zhouzhendong/p/8108676.html


题目传送门 - BZOJ1500


题意概括

Description

Input

输入的第1 行包含两个数N 和M(M ≤20 000),N 表示初始时数列中数的个数,M表示要进行的操作数目。
第2行包含N个数字,描述初始时的数列。
以下M行,每行一条命令,格式参见问题描述中的表格。
任何时刻数列中最多含有500 000个数,数列中任何一个数字均在[-1 000, 1 000]内。
插入的数字总数不超过4 000 000个,输入文件大小不超过20MBytes。

Output

对于输入数据中的GET-SUM和MAX-SUM操作,向输出文件依次打印结果,每个答案(数字)占一行。


题解

  splay乱维护就可以了。

  维护:区间sum,左max,右max,区间max,size

  这题要回收内存。

  还有,不用开longlong,int可过。

  还有,子列长度至少为1,那么就要把节点0的sum,Lmax,Rmax,Max全部赋值成-Inf

  注意哨兵节点的安插。


代码

#include <cstring>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cmath>
using namespace std;
const int Inf=1e9;
bool isd(char ch){
	return '0'<=ch&&ch<='9';
}
int read(){
	int res=0,f=1;
	char ch=getchar();
	while (!isd(ch)&&ch!='-')
		ch=getchar();
	if (ch=='-')
		f=-1,ch=getchar();
	while (isd(ch))
		res=(res<<1)+(res<<3)+ch-48,ch=getchar();
	return res*f;
}
const int S=500005;
int n,m,a[S];
int total,root,st[S],top,Lmax[S],Rmax[S],sum[S],val[S],Max[S];
int fa[S],son[S][2],rev[S],cov[S],size[S];
void clear_node(int x,int v){
	Lmax[x]=Rmax[x]=val[x]=sum[x]=Max[x]=v;
	rev[x]=0,cov[x]=-Inf,size[x]=1;
	fa[x]=son[x][0]=son[x][1]=0;
}
int new_node(int v){
	int x=top?st[top--]:++total;
	clear_node(x,v);
	return x;
}
void pushup(int x){
	if (!x)
		return;
	int ls=son[x][0],rs=son[x][1];
	sum[x]=sum[ls]+val[x]+sum[rs];
	size[x]=size[ls]+size[rs]+1;
	Lmax[x]=max(Lmax[ls],sum[ls]+val[x]+max(Lmax[rs],0));
	Rmax[x]=max(Rmax[rs],sum[rs]+val[x]+max(Rmax[ls],0));
	Max[x]=max(max(Max[ls],Max[rs]),max(Rmax[ls],0)+val[x]+max(Lmax[rs],0));
}
void pushson(int x,int r,int c){
	if (!x)
		return;
	if (r){
		rev[x]^=1;
		swap(Lmax[x],Rmax[x]);
		swap(son[x][0],son[x][1]);
	}
	if (c>=-1000)
		Max[x]=Lmax[x]=Rmax[x]=max(sum[x]=c*size[x],cov[x]=val[x]=c),rev[x]=0;
}
void pushdown(int x){
	int &ls=son[x][0],&rs=son[x][1],&r=rev[x],&c=cov[x];
	pushson(ls,r,c);
	pushson(rs,r,c);
	r=0,c=-Inf;
}
void pushadd(int x){
	if (fa[x])
		pushadd(fa[x]);
	pushdown(x);
}
int wson(int x){
	return son[fa[x]][1]==x;
}
void rotate(int x){
	if (!fa[x])
		return;
	int y=fa[x],z=fa[y],L=wson(x),R=L^1;
	if (z)
		son[z][wson(y)]=x;
	fa[x]=z,fa[y]=x,fa[son[x][R]]=y;
	son[y][L]=son[x][R],son[x][R]=y;
	pushup(y),pushup(x);
}
void splay(int x,int rt){
	if (!x)
		return;
	if (!rt)
		root=x;
	pushadd(x);
	for (int y=fa[x];fa[x]!=rt;rotate(x),y=fa[x])
		if (fa[y]!=rt)
			rotate(wson(x)==wson(y)?y:x);
}
int build(int pre,int L,int R){
	if (L>R)
		return 0;
	int mid=(L+R)>>1;
	int rt=new_node(a[mid]);
	fa[rt]=pre;
	if (L==R)
		return rt;
	son[rt][0]=build(rt,L,mid-1);
	son[rt][1]=build(rt,mid+1,R);
	pushup(rt);
	return rt;
}
int findkth(int x,int k){
	pushdown(x);
	if (size[son[x][0]]+1==k)
		return x;
	if (k<=size[son[x][0]])
		return findkth(son[x][0],k);
	else
		return findkth(son[x][1],k-size[son[x][0]]-1);
}
void erase(int x){
	if (!x)
		return;
	st[++top]=x;
	erase(son[x][0]);
	erase(son[x][1]);
}
int main(){
	n=read(),m=read();
	for (int i=1;i<=n;i++)
		a[i+1]=read();
	Lmax[0]=Rmax[0]=Max[0]=val[0]=-Inf;
	a[1]=a[n+2]=-Inf;
	root=build(0,1,n+2);
	for (int i=1;i<=m;i++){
		char op[10];
		scanf("%s",op);
		if (op[2]=='X'){
			printf("%d\n",Max[root]);
			continue;
		}
		int pos=read()+1,tot=read();
		if (op[0]=='I'){
			int x=findkth(root,pos),y=findkth(root,pos+1);
			splay(x,0);
			splay(y,x);
			pushdown(x);
			pushdown(y);
			int z=son[y][0];
			for (int i=1;i<=tot;i++)
				a[i]=read();
			son[y][0]=build(y,1,tot);
			pushup(y),pushup(x);
			continue;
		}
		int x=findkth(root,pos-1),y=findkth(root,pos+tot);
		splay(x,0);
		splay(y,x);
		int z=son[y][0];
		if (op[0]=='D')
			son[y][0]=fa[z]=0,erase(z);
		if (op[0]=='M')
			pushson(z,0,read());
		if (op[0]=='R')
			pushson(z,1,-Inf);
		if (op[0]=='G')
			printf("%d\n",sum[z]);
		pushup(y),pushup(x);
	}
	return 0;
}

  

posted @ 2017-12-25 11:43  zzd233  阅读(290)  评论(0编辑  收藏  举报