BZOJ 1500: [NOI2005]维修数列

Posted NeighThorn

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ 1500: [NOI2005]维修数列相关的知识,希望对你有一定的参考价值。

1500: [NOI2005]维修数列

Time Limit: 10 Sec  Memory Limit: 64 MB
Submit: 12880  Solved: 4112
[Submit][Status][Discuss]

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操作,向输出文件依次打印结果,每个答案(数字)占一行。

Sample Input

9 8
2 -6 3 5 1 -5 -3 6 3
GET-SUM 5 4
MAX-SUM
INSERT 8 3 -5 7 2
DELETE 12 1
MAKE-SAME 3 3 2
REVERSE 3 6
GET-SUM 5 4
MAX-SUM

Sample Output

-1
10
1
10

HINT

 

技术分享

 

Source

分析:

很久之前就写过...但是没写过...QAQ...没想到这道题还是写了一年(怎么又跨年了...

操作什么的其实就是把线段树换成了Splay...

insert:
把posi+1转到root,posi转到左儿子,新插入的作为posi的右儿子
delete:
把posi+tot转到root,posi-1转到左儿子,删掉posi-1的右儿子
make_same:
把posi+tot转到root,posi-1转到左儿子,posi-1的右儿子修改
reverse:
转法和上面一样,打标记
get_sum:
同上
max_sum:
每个节点维护lsum,rsum,msum

比较麻烦的就是一些边界问题...Zig_Zag的code可以完美滴处理这些问题,然而我只会特判...向Zig_Zag神犇学习...

代码:

其实我的代码还是有缺陷的...只不过可以过掉BZOJ的数据...

正确的写法应该是Zig_Zag那样的...如果把我的code的每次操作完的那两次旋转去掉是过不了的...

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
//by NeighThorn
#define inf 0x3f3f3f3f
using namespace std;

const int maxn=1000000+5;

int tail,stk[maxn];
int n,m,now,tot,root,w[maxn],no[maxn],ls[maxn],rs[maxn],fa[maxn],siz[maxn],sum[maxn],rev[maxn],lmax[maxn],rmax[maxn],mmax[maxn],lazy[maxn];

char opt[13];

inline void reverse(int x){
	if(x==0)
		return;
	swap(ls[x],rs[x]);
	swap(lmax[x],rmax[x]);
}

inline void make_same(int x,int y){
	if(x==0)
		return;
	w[x]=y;sum[x]=siz[x]*y;
	lmax[x]=rmax[x]=mmax[x]=max(y,sum[x]);//bu neng wei kong
}

inline void push_down(int x){
	if(x==0)
		return;
	if(rev[x])
		reverse(ls[x]),reverse(rs[x]),rev[ls[x]]^=1,rev[rs[x]]^=1,rev[x]=0;
	if(lazy[x]!=-inf)
		make_same(ls[x],lazy[x]),make_same(rs[x],lazy[x]),lazy[ls[x]]=lazy[rs[x]]=lazy[x],lazy[x]=-inf;
}

inline void update(int x){
	if(x==0)
		return;
	lmax[x]=max(lmax[ls[x]],sum[ls[x]]+w[x]+max(0,lmax[rs[x]]));
	rmax[x]=max(rmax[rs[x]],sum[rs[x]]+w[x]+max(0,rmax[ls[x]]));
	mmax[x]=max(max(mmax[ls[x]],mmax[rs[x]]),w[x]+max(0,rmax[ls[x]])+max(0,lmax[rs[x]]));
	sum [x]=sum[ls[x]]+sum[rs[x]]+w[x];
	siz [x]=siz[ls[x]]+siz[rs[x]]+1;
}

inline void zig(int x){ 
	int y=fa[x];
	update(x);update(y);
	if(rs[x])
		ls[y]=rs[x],fa[rs[x]]=y;
	else
		ls[y]=0;
	fa[x]=fa[y];
	if(fa[x]){
		if(ls[fa[y]]==y)
			ls[fa[y]]=x;
		else	
			rs[fa[y]]=x;
	}
	fa[y]=x,rs[x]=y;
	update(y),update(x);
}

inline void zag(int x){
	int y=fa[x];
	update(x);update(y);
	if(ls[x])
		rs[y]=ls[x],fa[ls[x]]=y;
	else
		rs[y]=0;
	fa[x]=fa[y];
	if(fa[x]){
		if(ls[fa[y]]==y)
			ls[fa[y]]=x;
		else
			rs[fa[y]]=x;
	}
	fa[y]=x,ls[x]=y;
	update(y),update(x);
}

inline void relax(int x,int y){
	if(x!=y)
		relax(fa[x],y);
	push_down(x);
}

inline void splay(int x,int z){
	relax(x,z);
	while(fa[x]!=z){
		int y=fa[x];
		if(fa[y]==z){
			if(ls[y]==x)
				zig(x);
			else
				zag(x);
		}
		else{
			if(ls[fa[y]]==y){
				if(ls[y]==x)
					zig(y),zig(x);
				else
					zag(x),zig(x);
			}
			else{
				if(rs[y]==x)
					zag(y),zag(x);
				else
					zig(x),zag(x);
			}
		}
	}
	update(x);
	if(!z)
		root=x;
	else
		update(z);
}

inline int get_num(void){
	if(tail)
		return stk[tail--];
	return ++tot;
}

inline int assign(int x){
	int tmp=get_num();
	rev[tmp]=0;
	w[tmp]=no[x];
	lazy[tmp]=-inf;
	lmax[tmp]=rmax[tmp]=mmax[tmp]=-inf;
	return tmp;
}

inline int build(int l,int r){
	if(l==r){
		int tmp=assign(l);
		update(tmp);return tmp;
	}
	int mid=(l+r)>>1,L=0,R=0,tmp=assign(mid);
	if(l<mid)
		L=build(l,mid-1);
	if(r>mid)
		R=build(mid+1,r);
	if(L)
		ls[tmp]=L,fa[L]=tmp;
	if(R)
		rs[tmp]=R,fa[R]=tmp;
	update(tmp);
	return tmp;
}

inline void del(int x){
	if(x==0)
		return;
	stk[++tail]=x;
	fa[x]=rev[x]=0;lazy[x]=-inf;
	lmax[x]=rmax[x]=mmax[x]=-inf;
	if(ls[x])
		del(ls[x]);
	if(rs[x])
		del(rs[x]);
	ls[x]=rs[x]=0;
}

inline int find(int rt,int x){
	push_down(rt);
	if(siz[ls[rt]]+1==x)
		return rt;
	else if(siz[ls[rt]]+1>x)
		return find(ls[rt],x);
	else
		return find(rs[rt],x-siz[ls[rt]]-1);
}

inline int read(void){
	char ch=getchar();int x=0,f=1;
	while(!(ch>=‘0‘&&ch<=‘9‘)){
		if(ch==‘-‘)
			f=-1;
		ch=getchar();
	}
	while(ch>=‘0‘&&ch<=‘9‘)
		x=x*10+ch-‘0‘,ch=getchar();
	return f*x;
}

signed main(void){
	memset(ls,0,sizeof(ls));
	memset(rs,0,sizeof(rs));
	memset(fa,0,sizeof(fa));
	memset(rev,0,sizeof(rev));
	memset(sum,0,sizeof(sum));
	memset(siz,0,sizeof(siz));
	memset(lmax,-inf,sizeof(lmax));
	memset(rmax,-inf,sizeof(rmax));
	memset(mmax,-inf,sizeof(mmax));
	memset(lazy,-inf,sizeof(lazy));
	tot=tail=0;
	n=read(),m=read();now=n;
	for(int i=1;i<=n;i++)
		no[i]=read();
	root=build(1,n);int pos,tot,x;
	while(m--){
		scanf("%s",opt);
		if(opt[0]==‘I‘){
			pos=read(),tot=read();
			for(int i=1;i<=tot;i++)
				no[i]=read();
			int tmproot=build(1,tot);
			if(now==0)
				root=tmproot;
			else if(pos==0)
				splay(find(root,pos+1),0),ls[root]=tmproot,fa[tmproot]=root,update(root);
			else if(pos==now)
				splay(find(root,pos),0),rs[root]=tmproot,fa[tmproot]=root,update(root);
			else
				splay(find(root,pos+1),0),splay(find(root,pos),root),rs[ls[root]]=tmproot,fa[tmproot]=ls[root],update(ls[root]),update(root);
			now+=tot;
		}
		else if(opt[0]==‘D‘){
			pos=read(),tot=read();
			if(pos==1&&pos+tot-1==now)
				root=0;
			else if(pos==1)
				splay(find(root,pos+tot),0),del(ls[root]),ls[root]=0,update(root);
			else if(pos+tot-1==now)
				splay(find(root,pos-1),0),del(rs[root]),rs[root]=0,update(root);
			else
				splay(find(root,pos+tot),0),splay(find(root,pos-1),root),del(rs[ls[root]]),rs[ls[root]]=0,update(ls[root]),update(root);
			now-=tot;
		}
		else if(opt[0]==‘M‘&&opt[2]==‘K‘){
			pos=read(),tot=read(),x=read();
			if(pos==1&&pos+tot-1==now)
				make_same(root,x),lazy[root]=x;
			else if(pos==1)
				splay(find(root,pos+tot),0),make_same(ls[root],x),lazy[ls[root]]=x;
			else if(pos+tot-1==now)
				splay(find(root,pos-1),0),make_same(rs[root],x),lazy[rs[root]]=x;
			else
				splay(find(root,pos+tot),0),splay(find(root,pos-1),root),make_same(rs[ls[root]],x),lazy[rs[ls[root]]]=x;
		}
		else if(opt[0]==‘R‘){
			pos=read(),tot=read();
			if(pos==1&&pos+tot-1==now)
				reverse(root),rev[root]^=1;
			else if(pos==1)
				splay(find(root,pos+tot),0),reverse(ls[root]),rev[ls[root]]^=1;
			else if(pos+tot-1==now)
				splay(find(root,pos-1),0),reverse(rs[root]),rev[rs[root]]^=1;
			else
				splay(find(root,pos+tot),0),splay(find(root,pos-1),root),reverse(rs[ls[root]]),rev[rs[ls[root]]]^=1;
		}
		else if(opt[0]==‘G‘){
			pos=read(),tot=read();
			if(tot==0)
				puts("0");
			else if(pos==1&&pos+tot-1==now)
				splay(find(root,now),0),splay(find(root,1),0),printf("%d\n",sum[root]);
			else if(pos==1)
				splay(find(root,pos+tot),0),printf("%d\n",sum[ls[root]]);
			else if(pos+tot-1==now)
				splay(find(root,pos-1),0),printf("%d\n",sum[rs[root]]);
			else
				splay(find(root,pos+tot),0),splay(find(root,pos-1),root),printf("%d\n",sum[rs[ls[root]]]);
		}
		else
			splay(find(root,now),0),splay(find(root,1),0),printf("%d\n",mmax[root]); 
		splay(find(root,1),0);splay(find(root,now),0);
	}
	return 0;
}//Cap ou pas cap. Cap.

  


By NeighThorn

以上是关于BZOJ 1500: [NOI2005]维修数列的主要内容,如果未能解决你的问题,请参考以下文章

bzoj:1500: [NOI2005]维修数列

BZOJ1500: [NOI2005]维修数列[splay ***]

BZOJ1500[NOI2005]维修数列

BZOJ1500: [NOI2005]维修数列

bzoj1500 [NOI2005]维修数列

bzoj1500: [NOI2005]维修数列