码迷,mamicode.com
首页 > 其他好文 > 详细

BZOJ 2329 HNOI 2011 括号修复 Splay维护最大连续子段和

时间:2015-01-08 21:45:30      阅读:272      评论:0      收藏:0      [点我收藏+]

标签:bzoj   splay   

题目大意:给出一个括号序列,问一段区间最少需要修改多少括号使得这一段括号变成一段完整的括号序列。


思路:题解见http://ydcydcy1.blog.163.com/blog/static/2160890402013116111134791/ OTZ ydc

维护起来稍微有些麻烦啊。。


CODE:


#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAX 100010
using namespace std;
#define WORKPATH (root->son[1]->son[0])

struct SplayTree *_nil;

struct SplayTree{
	int val,size;
	SplayTree *son[2],*father;
	
	int sum,l_min,l_max,r_min,r_max;
	bool reverse,invert;
	int change;

	bool Check() {
		return father->son[1] == this;
	}
	void Combine(SplayTree *a,bool dir) {
		son[dir] = a;
		a->father = this;
	}
	void Reverse() {
		if(this == _nil)	return ;
		reverse ^= 1;
		swap(l_min,r_min);
		swap(l_max,r_max);
		swap(son[0],son[1]);
	}
	void Invert() {
		if(this == _nil)	return ;
		invert ^= 1;
		l_min *= -1,l_max *= -1;
		r_min *= -1,r_max *= -1;
		sum *= -1,val *= -1;
		swap(l_min,l_max);
		swap(r_min,r_max);
	}
	void Change(int _) {
		if(this == _nil)	return ;
		change = val = _;
		sum = _ * size;
		l_min = r_min = min(0,_ * size);
		l_max = r_max = max(0,_ * size);
		reverse = invert = false;
	}
	void PushUp() {
		if(this == _nil)
			return ;
		size = son[0]->size + son[1]->size + 1;
		sum = son[0]->sum + son[1]->sum + val;
		l_min = min(son[0]->l_min,son[0]->sum + val + son[1]->l_min);
		l_max = max(son[0]->l_max,son[0]->sum + val + son[1]->l_max);
		r_min = min(son[1]->r_min,son[1]->sum + val + son[0]->r_min);
		r_max = max(son[1]->r_max,son[1]->sum + val + son[0]->r_max);		
	}
	void PushDown() {
		if(this == _nil)	return ;
		if(change) {
			son[0]->Change(change);
			son[1]->Change(change);
			change = 0;
		}
		if(invert) {
			son[0]->Invert();
			son[1]->Invert();
			invert = false;
		}
		if(reverse) {
			son[0]->Reverse();
			son[1]->Reverse();
			reverse = false;
		}
	}
}none,*nil = &none,*root;

char src[MAX];
int length,asks;

void Pretreatment()
{
	nil->son[0] = nil->son[1] = nil->father = nil;
	nil->sum = nil->val = nil->change = nil->size = 0;
	nil->reverse = nil->invert = false;
	_nil = nil;
}

inline SplayTree *NewSplay(int _)
{
	SplayTree *re = new SplayTree();
	re->val = re->sum = _;
	re->size = 1;
	re->l_min = re->r_min = min(_,0);
	re->l_max = re->r_max = max(_,0);
	re->son[0] = re->son[1] = re->father = nil;
	re->reverse = re->invert = false;
	re->change = 0;
	return re;
}

inline void Rotate(SplayTree *a,bool dir)
{
	SplayTree *f = a->father;
	f->PushDown(),a->PushDown();
	f->son[!dir] = a->son[dir];
	f->son[!dir]->father = f;
	a->son[dir] = f;
	a->father = f->father;
	f->father->son[f->Check()] = a;
	f->father = a;
	f->PushUp();
	if(root == f)	root = a;
}

SplayTree *BuildTree(int l,int r)
{
	if(l > r)	return nil;
	int mid = (l + r) >> 1;
	SplayTree *re = NewSplay(src[mid] == '(' ? -1:1);
	re->Combine(BuildTree(l,mid - 1),false);
	re->Combine(BuildTree(mid + 1,r),true);
	re->PushUp();
	return re;
}

inline void Splay(SplayTree *a,SplayTree *aim)
{
	while(a->father != aim) {
		if(a->father->father == aim)
			Rotate(a,!a->Check());
		else if(!a->father->Check()) {
			if(!a->Check())
				Rotate(a->father,true),Rotate(a,true);
			else	Rotate(a,false),Rotate(a,true);
		}
		else {
			if(a->Check())
				Rotate(a->father,false),Rotate(a,false);
			else	Rotate(a,true),Rotate(a,false);
		}
	}
	a->PushUp();
}

SplayTree *Find(SplayTree *a,int k)
{
	a->PushDown();
	if(a->son[0]->size >= k)	return Find(a->son[0],k);
	k -= a->son[0]->size;
	if(k == 1)	return a;
	return Find(a->son[1],k - 1);
}

inline void SplaySeg(int x,int y)
{
	x++,y++;
	Splay(Find(root,x - 1),nil);
	Splay(Find(root,y + 1),root);
}

char s[10];

int main()
{
	Pretreatment();
	cin >> length >> asks;
	scanf("%s",src + 1);
	root = BuildTree(0,length + 1);
	root->father = nil;
	for(int x,y,i = 1; i <= asks; ++i) {
		scanf("%s%d%d",s,&x,&y);
		SplaySeg(x,y);
		if(s[0] == 'R') {
			scanf("%s",s);
			WORKPATH->Change(s[0] == '(' ? -1:1);
		}
		else if(s[0] == 'Q')	printf("%d\n",((WORKPATH->l_max + 1) >> 1) + ((-WORKPATH->r_min + 1) >> 1));
		else if(s[0] == 'S')	WORKPATH->Reverse();
		else if(s[0] == 'I')	WORKPATH->Invert();
	}
	return 0;
}


BZOJ 2329 HNOI 2011 括号修复 Splay维护最大连续子段和

标签:bzoj   splay   

原文地址:http://blog.csdn.net/jiangyuze831/article/details/42526981

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!