BZOJ 1251: 序列终结者

题目地址:http://www.lydsy.com/JudgeOnline/problem.php?id=1251


题目大意:维护3种操作:区间加、区间翻转、询问区间Max。


算法讨论:

        说是“终结者”,其实只是一题入门题和模板题而已。

        区间翻转显然用的是Splay。

        然后就OK了。


Code:

/*
 * Problem:1251
 * Author:PYC
 */

#include 
#include 
#include 

#define maxn 1000000
#define oo 1000000000

using namespace std;

int n,m,tot,root;

struct node{
	int key,Max,add,l,r,ll,rr,fa;
	bool rev;
}tree[maxn];

void up(int rt){
	tree[rt].Max=max(tree[rt].key,max(tree[rt].l?tree[tree[rt].l].Max:-oo,tree[rt].r?tree[tree[rt].r].Max:-oo));
}

void down(int rt){
	if (tree[rt].add){
		tree[tree[rt].l].add+=tree[rt].add;
		tree[tree[rt].r].add+=tree[rt].add;
		tree[tree[rt].l].key+=tree[rt].add;
		tree[tree[rt].r].key+=tree[rt].add;
		tree[tree[rt].l].Max+=tree[rt].add;
		tree[tree[rt].r].Max+=tree[rt].add;
		tree[rt].add=0;
	}
	if (tree[rt].rev){
		tree[tree[rt].l].rev^=1;
		tree[tree[rt].r].rev^=1;
		swap(tree[tree[rt].l].l,tree[tree[rt].l].r);
		swap(tree[tree[rt].r].l,tree[tree[rt].r].r);
		swap(tree[tree[rt].l].ll,tree[tree[rt].l].rr);
		swap(tree[tree[rt].r].ll,tree[tree[rt].r].rr);
		tree[rt].rev=0;
	}
}

void build(int &rt,int l,int r){
	int mid=(l+r)/2;
	rt=++tot;
	if (l==r) return;
	if (mid-l){
		tree[rt].ll=mid-l;
		build(tree[rt].l,l,mid-1);
		tree[tree[rt].l].fa=rt;
	}
	if (r-mid){
		tree[rt].rr=r-mid;
		build(tree[rt].r,mid+1,r);
		tree[tree[rt].r].fa=rt;
	}
	up(rt);
}

int kth(int rt,int y){
	down(rt);
	if (y==tree[rt].ll+1) return rt;
	if (ytree[rt].ll+1) return kth(tree[rt].r,y-tree[rt].ll-1);
}

void zig(int rt){
	int t=tree[rt].l;
	tree[rt].l=tree[t].r;
	tree[rt].ll=tree[t].rr;
	tree[t].r=rt;
	tree[t].rr+=tree[rt].rr+1;
	tree[t].fa=tree[rt].fa;
	tree[rt].fa=t;
	tree[tree[rt].l].fa=rt;
	if (rt==tree[tree[t].fa].l) tree[tree[t].fa].l=t;
	else tree[tree[t].fa].r=t;
	up(rt);
	up(t);
}

void zag(int rt){
	int t=tree[rt].r;
	tree[rt].r=tree[t].l;
	tree[rt].rr=tree[t].ll;
	tree[t].l=rt;
	tree[t].ll+=tree[rt].ll+1;
	tree[t].fa=tree[rt].fa;
	tree[rt].fa=t;
	tree[tree[rt].r].fa=rt;
	if (rt==tree[tree[t].fa].l) tree[tree[t].fa].l=t;
	else tree[tree[t].fa].r=t;
	up(rt);
	up(t);
}

void splay(int x,int &rt){
	stack Q;
	for (int i=x;i;i=tree[i].fa) Q.push(i);
	while (!Q.empty()){
		down(Q.top());
		Q.pop();
	}
	int fa=tree[rt].fa;
	while (tree[x].fa!=fa){
		int y=tree[x].fa,z=tree[y].fa;
		if (z==fa){
			if (x==tree[y].l) zig(y);
			else zag(y);
		}
		else if (y==tree[z].l){
			if (x==tree[y].l){zig(z);zig(y);}
			else{zag(y);zig(z);}
		}
		else{
			if (x==tree[y].r){zag(z);zag(y);}
			else{zig(y);zag(z);}
		}
	}
	rt=x;
}

int ask(int l,int r){
	splay(kth(root,l),root);
	splay(kth(root,r+2),tree[root].r);
	up(root);
	return tree[tree[tree[root].r].l].Max;
}

void add(int l,int r,int d){
	splay(kth(root,l),root);
	splay(kth(root,r+2),tree[root].r);
	up(root);
	tree[tree[tree[root].r].l].key+=d;
	tree[tree[tree[root].r].l].Max+=d;
	tree[tree[tree[root].r].l].add+=d;
}

void reverse(int l,int r){
	splay(kth(root,l),root);
	splay(kth(root,r+2),tree[root].r);
	up(root);
	tree[tree[tree[root].r].l].rev^=1;
	swap(tree[tree[tree[root].r].l].l,tree[tree[tree[root].r].l].r);
	swap(tree[tree[tree[root].r].l].ll,tree[tree[tree[root].r].l].rr);
}

int main(){
	scanf("%d%d",&n,&m);
	build(root,0,n+1);
	for (int i=1;i<=m;++i){
		int x;
		scanf("%d",&x);
		if (x==3){
			int l,r;
			scanf("%d%d",&l,&r);
			printf("%d\n",ask(l,r));
		}
		if (x==1){
			int l,r,d;
			scanf("%d%d%d",&l,&r,&d);
			add(l,r,d);
		}
		if (x==2){
			int l,r;
			scanf("%d%d",&l,&r);
			reverse(l,r);
		}
	}
	return 0;
}

By Charlie Pan

Mar 4,2014

你可能感兴趣的:(BZOJ,BZOJ,Splay,数据结构,平衡树)