• 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
    ",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
    ",sum[z]);
    		pushup(y),pushup(x);
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    log4net的使用
    数据库概念及构成
    基于C#WPF框架——动画
    基于C# WPF框架的贪吃蛇
    使用Teigha.net读取CAD的常用功能模块
    Teigha.net实体属性注释
    .net(C#数据库访问) Mysql,Sql server,Sqlite,Access四种数据库的连接方式
    Delphi解析修改Json文件,基于superobject.pas(ISuperObject)
    C++结构体与Delphi结构体相互传参,结构体中包含结构体的嵌套,数组指针
    C++ Json解析CJsonObject的详细使用
  • 原文地址:https://www.cnblogs.com/zhouzhendong/p/BZOJ1500.html
Copyright © 2020-2023  润新知