维护序列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\n",sum[x]); 
			} 
			else printf("%d\n",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\n",x,val[x]);
	if(t[x].ch[1])dfs(t[x].ch[1]);
}
/*inline void debug()
{
	printf("序列:::::\n");
	dfs(rt);
	printf("\n\nrt:%d\n",rt);
	inc(i,1,14)
	{
		int x=i;
		printf("--------------------------------------\n");
		printf("x:%d\n",x);
		printf("ch[0]:%d\n",t[x].ch[0]);
		printf("ch[1]:%d\n",t[x].ch[1]);
		printf("ls:%d\n",ls[x]);
		printf("rs:%d\n",rs[x]);
		printf("ms:%d\n",ms[x]);
		printf("sum:%d\n",sum[x]);
		printf("size:%d\n",size[x]);
		printf("val:%d\n",val[x]);
		printf("lazy:%d\n",lazy[x]);
		printf("rev:%d\n",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\n",sum[x]); 
			} 
			else printf("%d\n",ms[rt]);
		}
		
	}
	re 0;
}
posted @ 2019-07-30 22:17  凉如水  阅读(173)  评论(0编辑  收藏  举报