zoukankan      html  css  js  c++  java
  • 维护序列NOI2005

    调了一个下午
    最近做题都这样吧,思路很简单,代码很繁琐
    要努力提高代码能力
    细节太多很恶心;

    详细地说一说吧

    • Pushup
    1. 维护最大连续前缀和ls
    2. 最大连续后缀和rs
    3. 以及最大子序列和ms
    	int l=t[x].ch[0],r=t[x].ch[1];
    	size[x]=size[l]+size[r]+1;
    	ls[x]=max(ls[l],sum[l]+val[x]+ls[r]);
    	rs[x]=max(rs[r],sum[r]+val[x]+rs[l]);
    	ms[x]=max(ms[l],max(ms[r],rs[l]+ls[r]+val[x]));
    	sum[x]=sum[l]+sum[r]+val[x];	
    
    • Pushdown
    1. lazy数组表示是否make_same,因为same值有可能为0
    2. 并且因为lazy后rev无用
    3. ls[r]如果是负数,还不如不加(0)
    4. rev时:ls[x]与rs[x]也要交换
    if(lazy[x])
    	if(lazy[x])
    	{
    		int l=t[x].ch[0],r=t[x].ch[1];
    		if(l)
                    {
                        lazy[l]=1;val[l]=val[x];sum[l]=size[l]*val[x];
                        ls[l]=rs[l]=max(sum[l],0);ms[l]=max(sum[l],val[x]);
                    }
    		if(r)
                    {
                        lazy[r]=1;val[r]=val[x];sum[r]=size[r]*val[x];
                        ls[r]=rs[r]=max(sum[r],0);ms[r]=max(sum[r],val[x]);
                    }
    		rev[x]=lazy[x]=0;
    	}
    	else if(rev[x])
    	{
    		int l=t[x].ch[0],r=t[x].ch[1];
    		rev[l]^=1;rev[r]^=1;
    		swap(ls[l],rs[l]);swap(ls[r],rs[r]);
    		swap(t[l].ch[1],t[l].ch[0]);swap(t[r].ch[0],t[r].ch[1]);		
    		rev[x]=0;
    	}
    		
    
    • Build
    1. 回收机制使用,注意清空
    2. 叶子点赋值
    
    int build(int l,int r,int f)
    {	
    	if(l>r) re 0;
    	int x,mid=(l+r)>>1;
    	if(top)
    	{
    		x=q[top];--top;
    		lazy[x]=rev[x]=0;	
    	}
    	else x=++tot;
    	fa[x]=f;val[x]=num[mid];
    	t[x].ch[0]=build(l,mid-1,x);t[x].ch[1]=build(mid+1,r,x);
    	if(l==r)
    	{
    		ms[x]=sum[x]=num[mid];
    		ls[x]=rs[x]=max(num[mid],-1);
    		size[x]=1;
    	}
    	pushup(x);
    	re x;
    }
    
    
    • Split
    1. 就是将所求区间弄到根节点的右子树的左儿子里,返回左儿子
    inline int split(int l,int r)
    {
    	l=kth(l);
    	r=kth(r+1);
    	splay(l,0);
    	splay(r,l);
    	re t[r].ch[0];
    }
    
    • INSERT
    1. 建一颗平衡树,放在右儿子的左子树里
      因为它的左儿子(0)可能没有左子树
    inline void INSERT(int posi,int y)
    {
    	inc(i,1,y)rd(num[i]);
    	int nrt=build(1,y,0);
    	int x=kth(posi+1),z=kth(posi+2);
    	splay(x,0);splay(z,x);
    	t[z].ch[0]=nrt;
    	fa[nrt]=z;
    	pushup(z);pushup(x);
    } 
    
    • DELETE
    1. 记录一下垃圾编号,回收
    • 前趋操作
    	if(s[0]!='M'||s[2]!='X')
    			rd(posi),rd(toto);
    		if(s[0]=='I')//insert
    		{
    			INSERT(posi,toto); 
    		}
    		else if(s[0]=='D')//delete
    		{
    			x=split(posi,toto+posi);
    			DELETE(x);
    			t[fa[x]].ch[0]=0;//清除其在父节点信息
    			pushup(fa[x]);//更新
    			pushup(fa[fa[x]]);//更新至根节点
    		}
    		else if(s[0]=='R')//reverse
    		{
    			x=split(posi,posi+toto);
    			if(!lazy[x])
    			{
    			//初始修改
    				rev[x]^=1;
    				swap(t[x].ch[0],t[x].ch[1]);
    				swap(ls[x],rs[x]);
    				pushup(fa[x]),pushup(fa[fa[x]]);//更新至根节点
    			}
    		}
    		else if(s[2]=='K')//make_same
    		{
    			rd(c);
    			x=split(posi,posi+toto);
    			//初始修改
    			lazy[x]=1;
    			val[x]=c;
    			sum[x]=c*size[x];
    			if(c>0)
    				ls[x]=rs[x]=ms[x]=sum[x];
    			else 
    			{
    				ls[x]=rs[x]=0;
    				ms[x]=c;
    			}
    			pushup(fa[x]);pushup(fa[fa[x]]);//更新至根节点
    		}
    		else 
    		{
    			if(s[0]=='G')//get_sum
    			{
    				x=split(posi,toto+posi);
    				printf("%d
    ",sum[x]); 
    			} 
    			else printf("%d
    ",ms[rt]);//max_sum
    		}
    

    完整代码

    #include<bits/stdc++.h>
    #define re return
    #define MAX(a,b) (a)>(b)?(a):(b)
    #define inc(i,l,r) for(int i=l;i<=r;++i)
    const int maxn=500005;
    template<typename T>inline void rd(T&x)
    {
    	char c;bool f=0;
    	while((c=getchar())<'0'||c>'9')if(c=='-')f=1;
    	x=c^48;
    	while((c=getchar())>='0'&&c<='9')x=x*10+(c^48);
    	if(f)x=-x;
    }
    using namespace std;
    int rt,tot,q[maxn],top,n,m,num[maxn],fa[maxn];
    int sum[maxn],size[maxn],val[maxn],lazy[maxn],rev[maxn],ls[maxn],rs[maxn],ms[maxn];
    struct node{
    	int	ch[2];
    }t[maxn];
    
    inline void pushup(int x)
    {
    	int l=t[x].ch[0],r=t[x].ch[1];
    	size[x]=size[l]+size[r]+1;
    	ls[x]=max(ls[l],sum[l]+val[x]+ls[r]);
    	rs[x]=max(rs[r],sum[r]+val[x]+rs[l]);
    	ms[x]=max(ms[l],max(ms[r],rs[l]+ls[r]+val[x]));
    	sum[x]=sum[l]+sum[r]+val[x];	
    }
    
    inline void pushdown(int x)
    {
    	if(lazy[x])
    	{
    		int l=t[x].ch[0],r=t[x].ch[1];
    		if(l){lazy[l]=1;val[l]=val[x];sum[l]=size[l]*val[x];ls[l]=rs[l]=max(sum[l],-1);ms[l]=max(sum[l],val[x]);}
    		if(r){lazy[r]=1;val[r]=val[x];sum[r]=size[r]*val[x];ls[r]=rs[r]=max(sum[r],-1);ms[r]=max(sum[r],val[x]);}
    		rev[x]=lazy[x]=0;
    	}
    	else if(rev[x])
    	{
    		int l=t[x].ch[0],r=t[x].ch[1];
    		rev[l]^=1;rev[r]^=1;
    		swap(ls[l],rs[l]);swap(ls[r],rs[r]);
    		swap(t[l].ch[1],t[l].ch[0]);swap(t[r].ch[0],t[r].ch[1]);		
    		rev[x]=0;
    	}
    		
    }
    
    inline bool chk(int x){re t[fa[x]].ch[1]==x;}
    inline void rotate(int x)
    {
    	int y=fa[x],z=fa[y],k=chk(x),w=t[x].ch[k^1];
    	t[y].ch[k]=w;fa[w]=y;
    	t[z].ch[chk(y)]=x;fa[x]=z;
    	t[x].ch[k^1]=y;fa[y]=x;
    	pushup(y);pushup(x);
    }
    
    inline void splay(int x,int goal=0)
    {
    	while(fa[x]!=goal)
    	{
    		int y=fa[x],z=fa[y];
    		if(z!=goal)
    		chk(x)==chk(y)?rotate(y):rotate(x);
    		rotate(x);
    	}
    	if(!goal)rt=x;
    }
    
    int build(int l,int r,int f)
    {	
    	if(l>r) re 0;
    	int x,mid=(l+r)>>1;
    	if(top)
    	{
    		x=q[top];--top;
    		lazy[x]=rev[x]=0;	
    	}
    	else x=++tot;
    	fa[x]=f;val[x]=num[mid];
    	t[x].ch[0]=build(l,mid-1,x);t[x].ch[1]=build(mid+1,r,x);
    	if(l==r)
    	{
    		ms[x]=sum[x]=num[mid];
    		ls[x]=rs[x]=max(num[mid],-1);
    		size[x]=1;
    	}
    	pushup(x);
    	re x;
    }
    
    inline int kth(int k)
    {
    	int u=rt;
    	while(1)
    	{
    		pushdown(u);
    		int y=t[u].ch[0];
    		if(k>size[y]+1)k=k-1-size[y],u=t[u].ch[1];
    		else if(k<=size[y])u=t[u].ch[0];
    		else re u;
    	}
    }
    
    inline int split(int l,int r)
    {
    	l=kth(l);
    	r=kth(r+1);
    	splay(l,0);
    	splay(r,l);
    	re t[r].ch[0];
    }
    
    inline void INSERT(int posi,int y)
    {
    	inc(i,1,y)rd(num[i]);
    	int nrt=build(1,y,0);
    	int x=kth(posi+1),z=kth(posi+2);
    	splay(x,0);splay(z,x);
    	t[z].ch[0]=nrt;
    	fa[nrt]=z;
    	pushup(z);pushup(x);
    } 
    
    inline void DELETE(int x)
    {
    	q[++top]=x;
    	if(t[x].ch[0])DELETE(t[x].ch[0]);
    	if(t[x].ch[1])DELETE(t[x].ch[1]);
    } 
    
    inline void dfs(int x)
    {
    	pushdown(x);
    	if(t[x].ch[0])dfs(t[x].ch[0]);
    	printf("%d %d
    ",x,val[x]);
    	if(t[x].ch[1])dfs(t[x].ch[1]);
    }
    /*inline void debug()
    {
    	printf("序列:::::
    ");
    	dfs(rt);
    	printf("
    
    rt:%d
    ",rt);
    	inc(i,1,14)
    	{
    		int x=i;
    		printf("--------------------------------------
    ");
    		printf("x:%d
    ",x);
    		printf("ch[0]:%d
    ",t[x].ch[0]);
    		printf("ch[1]:%d
    ",t[x].ch[1]);
    		printf("ls:%d
    ",ls[x]);
    		printf("rs:%d
    ",rs[x]);
    		printf("ms:%d
    ",ms[x]);
    		printf("sum:%d
    ",sum[x]);
    		printf("size:%d
    ",size[x]);
    		printf("val:%d
    ",val[x]);
    		printf("lazy:%d
    ",lazy[x]);
    		printf("rev:%d
    ",rev[x]);
    	}
    }
    */
    int main()
    {
    	int cnt=0;
    	char s[25]; 
    	rd(n),rd(m);
    	inc(i,2,n+1)rd(num[i]);
    	num[1]=num[n+2]=ms[0]=-2e9;
    	rt=build(1,n+2,0);
    	
    	
    	int x,posi,toto,c; 
    	inc(i,1,m)
    	{
    		scanf("%s",s);
    		if(s[0]!='M'||s[2]!='X')
    			rd(posi),rd(toto);
    		if(s[0]=='I')
    		{
    			INSERT(posi,toto); 
    		}
    		else if(s[0]=='D')
    		{
    			x=split(posi,toto+posi);
    			DELETE(x);
    			t[fa[x]].ch[0]=0;
    			pushup(fa[x]);
    			pushup(fa[fa[x]]);
    		}
    		else if(s[0]=='R')
    		{
    			x=split(posi,posi+toto);
    			if(!lazy[x])
    			{
    				rev[x]^=1;
    				swap(t[x].ch[0],t[x].ch[1]);
    				swap(ls[x],rs[x]);
    				pushup(fa[x]),pushup(fa[fa[x]]);
    			}
    		}
    		else if(s[2]=='K')
    		{
    			rd(c);
    			x=split(posi,posi+toto);
    			lazy[x]=1;
    			val[x]=c;
    			sum[x]=c*size[x];
    			if(c>0)
    				ls[x]=rs[x]=ms[x]=sum[x];
    			else 
    			{
    				ls[x]=rs[x]=0;
    				ms[x]=c;
    			}
    			pushup(fa[x]);pushup(fa[fa[x]]);
    		}
    		else 
    		{
    			if(s[0]=='G')
    			{
    				x=split(posi,toto+posi);
    				printf("%d
    ",sum[x]); 
    			} 
    			else printf("%d
    ",ms[rt]);
    		}
    		
    	}
    	re 0;
    }
    
  • 相关阅读:
    highcharts延迟加载及刷新数据
    canvas实现固定元素背景雪花效果
    jquery自定义分页插件(带回调函数)
    sqlserver error 40解决方案
    canvas实现刮图效果
    canvas转换图像格式及尺寸
    CentOS 7上安装.Net Core运行环境
    centos环境下docker安装redis并挂载外部配置和数据
    Linux mv命令
    .NetCore 3.x Signalr JavaScript客户端使用
  • 原文地址:https://www.cnblogs.com/lsyyy/p/11273179.html
Copyright © 2011-2022 走看看