[NOI2005]维护数列 解题报告

①学会了维护最大连续子序列,跟最长全0连续子序列其实差不多;我一开始做麻烦了(用了前缀和。。)。

一些需要注意的细节:

②插入新节点的时候要注意维护其儿子节点的父指针;

③pushdown的位置不是随便放的,它应该放在对该节点进行询问之前。

④覆盖标记应该设为无穷,而不是0;因为0也可能是需要覆盖的。

⑤翻转标记应该使用^=标记,而不是=。

#include<iostream>
using namespace std;
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
struct SS{
	SS * f,* c[2];
	bool is_root;
	int size,data,sum,lmax,rmax,max;
	int lazy;
	bool flag;
}*nil=new SS((SS){nil,nil,nil,0,0,0,0,-1E7,-1E7,-1E7}),*root=new SS((SS){nil,nil,nil,1,2,-1E6,-2E6,-1E6,-1E6,-1E6});
int T;
inline void Out(SS * x){
	//printf("%d(%d) ",x->data,T++);
	cout<<"("<<x->f->data<<")"<<x->data<<":"<<x->size<<"(Size) "<<x->sum<<"(Sum) "<<x->lmax<<"(Lmax) "<<x->rmax<<"(Rmax) "<<x->max<<"(Max)\n";
}
inline void mtn(SS * x){
	x->size=x->c[0]->size+x->c[1]->size+1;
	x->sum=x->c[0]->sum+x->c[1]->sum+x->data;
	x->lmax=max(x->c[0]->lmax,max(x->c[0]->sum+x->data,x->c[0]->sum+x->data+x->c[1]->lmax));
	x->rmax=max(x->c[1]->rmax,max(x->c[1]->sum+x->data,x->c[1]->sum+x->data+x->c[0]->rmax));
	x->max=max(x->data,max(x->lmax,max(x->rmax,max(x->c[0]->rmax+x->data,max(x->c[0]->rmax+x->data+x->c[1]->lmax,max(x->data+x->c[1]->lmax,max(x->c[0]->max,x->c[1]->max)))))));
}
inline void re_paint(SS * x){
	if(x!=nil){
		swap(x->c[0],x->c[1]);
		swap(x->lmax,x->rmax);
		x->flag^=1;
	}
}
inline void sa_paint(SS * x,int A){
	if(x!=nil){
		x->data=A;
		x->sum=A*x->size;
		x->lazy=A;
		if(A<0)x->lmax=x->rmax=x->max=A;
		else x->lmax=x->rmax=x->max=A*x->size;
	}
}
inline void pushdown(SS * x){
	if(x->flag){
		re_paint(x->c[0]);
		re_paint(x->c[1]);
		x->flag=0;
	}
	if(x->lazy!=-0x7fffffff){
		sa_paint(x->c[0],x->lazy);
		sa_paint(x->c[1],x->lazy);
		x->lazy=-0x7fffffff;
	}
}
inline void out(SS * x){
	if(x==nil)return;
	pushdown(x);
	out(x->c[0]);
	Out(x);
	out(x->c[1]);
}
inline void zig(SS * x,bool D){
	SS * ftr=x->f;
	x->f=ftr->f;
	//cout<<x->data<<"->"<<x->c[0]->data<<" "<<x->c[1]->data<<"------>"<<ftr->data<<"->"<<ftr->c[0]->data<<" "<<ftr->c[1]->data<<endl;
	if(ftr->is_root)ftr->is_root=0,x->is_root=1;
	if(x->f->c[1]==ftr)x->f->c[1]=x;
	else x->f->c[0]=x;
	ftr->c[D]=x->c[!D];
	ftr->c[D]->f=ftr;
	x->c[!D]=ftr;
	ftr->f=x;
	mtn(ftr);
	//cout<<"Zig:"<<x->data<<"->"<<x->c[0]->data<<" "<<x->c[1]->data<<"------>"<<ftr->data<<"->"<<ftr->c[0]->data<<" "<<ftr->c[1]->data<<endl;
}
inline void splay(SS * x){
	/*cout<<"S:";
	out(root);*/
	for(bool D;!x->is_root;zig(x,D)){
		D=x->f->c[1]==x;
		if(!x->f->is_root&&D==(x->f->f->c[1]==x->f))zig(x->f,D);
	}
	root=x;
	mtn(x);/*
	cout<<"Play\n";
	out(root);
	cout<<"\n";*/
}
inline void search(SS * x,int A){
	//cout<<x->data<<endl;
	pushdown(x);
	while(x->c[0]->size!=A-1){
		//cout<<"Search:"<<x->data<<","<<A<<"("<<x->size<<")"<<x->c[0]->data<<"("<<x->c[0]->size<<")\n";
		if(x->c[0]->size>=A)x=x->c[0];
		else A-=x->c[0]->size+1,x=x->c[1];
		pushdown(x);
	}
	splay(x);
}
inline void open(int l,int L){//(l,r)
	//cout<<"Open:"<<l<<"->"<<L<<endl;
	search(root,l);
	//out(root);
	root=root->c[1];
	root->is_root=1;
	search(root,L+1);
}
inline void close(){
	mtn(root);
	root->is_root=0;
	root=root->f;
	mtn(root);
}
char * ptr=(char *)malloc(30000000);
inline int in(){
	bool flag=0;
	while(*ptr<'0'||*ptr>'9')
		if(*ptr++=='-')
			flag=1;
	int x=0;
	while(*ptr>47&&*ptr<58)x=x*10+*ptr++-'0';
	if(flag)return -x;
	return x;
}
int main(){
	freopen("seq2005.in","r",stdin);
	freopen("seq2005.out","w",stdout);
	root->c[0]=new SS((SS){root,nil,nil,0,1,-1E6,-1E6,-1E6,-1E6,-1E6});
	root->lazy=-0x7fffffff;
	root->c[0]->lazy=-0x7fffffff;
	
	fread(ptr,1,30000000,stdin);
	SS * tmp;
	open(1,0);
	int posi,tot=in(),M=in(),c;
	while(tot--){
		root->c[0]=new SS((SS){root,root->c[0],nil,0,0,in()});
		root->c[0]->c[0]->f=root->c[0];
		root->c[0]->lazy=-0x7fffffff;
		mtn(root->c[0]);
	}
	close();
	while(M--){
		while(*ptr<'A'||*ptr>'Z')++ptr;
		ptr+=2;
		switch(*ptr){
			case 'S':
				posi=in()+1,tot=in();
				open(posi,0);
				while(tot--){
					root->c[0]=new SS((SS){root,root->c[0],nil,0,0,in()});
					root->c[0]->c[0]->f=root->c[0];
					root->c[0]->lazy=-0x7fffffff;
					mtn(root->c[0]);
				}
				close();
				break;
			case 'L':
				posi=in(),tot=in();
				open(posi,tot);
				root->c[0]=nil;
				close();
				break;
			case 'K':
				ptr+=4;
				posi=in(),tot=in();
				open(posi,tot);
				sa_paint(root->c[0],in());
				close();
				break;
			case 'V':
				posi=in(),tot=in();
				open(posi,tot);
				re_paint(root->c[0]);
				close();
				break;
			case 'T':
				ptr+=2;
				posi=in(),tot=in();
				open(posi,tot);
				printf("%d\n",root->c[0]->sum);
				close();
				break;
			case 'X':
				ptr+=5;
				printf("%d\n",root->max);
				break;
		}/*
		cout<<M<<":";
		T=0;
		out(root);
		cout<<endl;*/
	}
}



你可能感兴趣的:(平衡树)