首页 > 代码库 > BZOJ 2329 HNOI 2011 括号修复 Splay维护最大连续子段和
BZOJ 2329 HNOI 2011 括号修复 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维护最大连续子段和
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。