传送魔法

  一开始以为可以直接线段树的,好像还是不行……还是得用Spaly,然后就没啥了。

#include<cstdio>
#include<algorithm>
#define MN 210000
using namespace std; inline int read(){
int ca=getchar(),p=;
while (ca<''||ca>'') ca=getchar();
while (ca>=''&&ca<='') p=p*+ca-,ca=getchar();
return p;
}
struct na{int s,qm,qi,hm,hi;na(int _s=,int _qm=,int _qi=,int _hm=,int _hi=):s(_s),qm(_qm),qi(_qi),hm(_hm),hi(_hi){};};
struct tree{
int f,c[],k,s,S;
na w;
bool rev,cg;
}t[MN];
char s[MN];
int n,m,num=,st[MN],top,root,l,r;
na hb(na a,na b){
na c;
c.s=a.s+b.s;
c.qm=max(a.qm,b.qm+a.s);
c.qi=min(a.qi,b.qi+a.s);
c.hm=max(b.hm,a.hm+b.s);
c.hi=min(b.hi,a.hi+b.s);
return c;
}
inline void REV(int p){
if (!p) return;
t[p].w=na(t[p].w.s,t[p].w.hm,t[p].w.hi,t[p].w.qm,t[p].w.qi);
swap(t[p].c[],t[p].c[]);
t[p].rev^=;
}
inline void REP(int p,int s){
if (!p) return;t[p].k=s;t[p].rev=t[p].cg=;
if (s==) t[p].w=na(t[p].S,t[p].S,,t[p].S,);else t[p].w=na(-t[p].S,,-t[p].S,,-t[p].S);
t[p].s=s;
}
inline void CG(int p){
if (!p) return;
t[p].cg^=;t[p].k*=-;
t[p].w=na(-t[p].w.s,-t[p].w.qi,-t[p].w.qm,-t[p].w.hi,-t[p].w.hm);
}
inline void gx(int p){
if (t[p].k==) t[p].w=na(,,,,);else t[p].w=na(-,,-,,-);
if (t[p].c[])t[p].w=hb(t[t[p].c[]].w,t[p].w);
if (t[p].c[])t[p].w=hb(t[p].w,t[t[p].c[]].w);
t[p].S=t[t[p].c[]].S+t[t[p].c[]].S+;
}
inline void pd(int p){
if (t[p].s) REP(t[p].c[],t[p].s),REP(t[p].c[],t[p].s),t[p].s=;
if (t[p].rev) REV(t[p].c[]),REV(t[p].c[]),t[p].rev=;
if (t[p].cg) CG(t[p].c[]),CG(t[p].c[]),t[p].cg=;
}
void build(int &p,int l,int r){
if (l>r) return;
int mid=l+r>>;
p=mid+;t[p].s=t[p].rev=;
if (s[mid]=='(') t[p].k=;else t[p].k=-;
build(t[p].c[],l,mid-);build(t[p].c[],mid+,r);
t[t[p].c[]].f=t[t[p].c[]].f=p;
gx(p);
}
void rot(int &p,bool bo){
int k=t[p].c[bo];
t[p].c[bo]=t[k].c[!bo];
t[k].c[!bo]=p;
t[t[p].c[bo]].f=p;
t[k].f=t[p].f;
t[p].f=k;
gx(p);gx(k);
p=k;
}
inline bool gc(int p){return t[t[p].f].c[]==p;}
inline void ph(int p){if (t[p].f==root) rot(root,gc(p));else rot(t[t[t[p].f].f].c[gc(t[p].f)],gc(p));}
void spaly(int p,int f){
top=;
for (int i=p;i;i=t[i].f) st[++top]=i;
while (top) pd(st[top--]);
while (t[p].f!=f)
if (t[t[p].f].f==f) ph(p);else
if (gc(p)==gc(t[p].f)) ph(t[p].f),ph(p);else ph(p),ph(p);
}
int fi(int p,int k){
pd(p);
if (t[t[p].c[]].S>=k) return fi(t[p].c[],k);else
if (t[t[p].c[]].S+==k) return p;else return fi(t[p].c[],k--t[t[p].c[]].S);
}
inline void rep(){
int l,r;
l=fi(root,read());r=fi(root,read()+);scanf("%s",s);
spaly(l,);spaly(r,l);
REP(t[r].c[],s[]=='('?:-);
}
inline void sw(){
int l,r;
l=fi(root,read());r=fi(root,read()+);
spaly(l,);spaly(r,l);
REV(t[r].c[]);
}
inline void cg(){
int l,r;
l=fi(root,read());r=fi(root,read()+);
spaly(l,);spaly(r,l);
CG(t[r].c[]);
}
inline void que(){
int l,r;
l=fi(root,read());r=fi(root,read()+);
spaly(l,);spaly(r,l);
printf("%d\n",(t[t[r].c[]].w.hm+>>)+(-t[t[r].c[]].w.qi+>>));
}
int main(){
n=read();m=read();
scanf("%s",s+);
build(root,,n+);
while (m--){
scanf("%s",s);
if (s[]=='R') rep();else
if (s[]=='S') sw();else
if (s[]=='I') cg();else que();
}
}

2329: [HNOI2011]括号修复的更多相关文章

  1. BZOJ 2329: [HNOI2011]括号修复( splay )

    把括号序列后一定是))))((((这种形式的..所以维护一个最大前缀和l, 最大后缀和r就可以了..答案就是(l+1)/2+(r+1)/2...用splay维护,O(NlogN). 其实还是挺好写的, ...

  2. ●BZOJ 2329 [HNOI2011]括号修复.cpp

    题链: http://www.lydsy.com/JudgeOnline/problem.php?id=2329 题解: Splay 类似 BZOJ 2329 [HNOI2011]括号修复 只是多了一 ...

  3. 【BZOJ】2329: [HNOI2011]括号修复(splay+特殊的技巧)

    http://www.lydsy.com/JudgeOnline/problem.php?id=2329 和前一题一样,不就多了个replace操作吗.好,就打一下. 然后交上去wa了........ ...

  4. BZOJ 2329: [HNOI2011]括号修复 [splay 括号]

    题目描述 一个合法的括号序列是这样定义的: 空串是合法的. 如果字符串 S 是合法的,则(S)也是合法的. 如果字符串 A 和 B 是合法的,则 AB 也是合法的. 现在给你一个长度为 N 的由‘(' ...

  5. 2329: [HNOI2011]括号修复 - BZOJ

    恶心的splay,打标记的时候还有冲突,要特别小心 上次写完了,查了半天没查出错来,于是放弃 今天对着标程打代码,终于抄完了,我已经不想再写了 const maxn=; type node=recor ...

  6. bzoj千题计划222:bzoj2329: [HNOI2011]括号修复(fhq treap)

    http://www.lydsy.com/JudgeOnline/problem.php?id=2329 需要改变的括号序列一定长这样 :)))((( 最少改变次数= 多余的‘)’/2 [上取整] + ...

  7. 【BZOJ2329/2209】[HNOI2011]括号修复/[Jsoi2011]括号序列 Splay

    [BZOJ2329/2209][HNOI2011]括号修复/[Jsoi2011]括号序列 题解:我们的Splay每个节点维护如下东西:左边有多少多余的右括号,右边有多少多余的左括号,同时为了反转操作, ...

  8. BZOJ 2329/2209 [HNOI2011]括号修复 (splay)

    题目大意: 让你维护一个括号序列,支持 1.区间修改为同一种括号 2.区间内所有括号都反转 3.翻转整个区间,括号的方向不变 4.查询把某段区间变为合法的括号序列,至少需要修改多少次括号 给跪了,足足 ...

  9. BZOJ2329 [HNOI2011]括号修复

    把左括号看做$1$,右括号看做$-1$,于是查询操作等于查询一个区间左边右边最大(最小)子段和 支持区间翻转,反转,覆盖操作...注意如果有覆盖操作,之前的操作全部作废了...于是在下传标记的时候要最 ...

随机推荐

  1. LeetCode #1 TwoSum

    Description Given an array of integers, return indices of the two numbers such that they add up to a ...

  2. [置顶] MVC输出缓存(OutputCache参数详解)

    1.学习之前你应该知道这些 几乎每个项目都会用到缓存,这是必然的.以前在学校时做的网站基本上的一个标准就是1.搞定增删改查2.页面做的不要太差3.能运行(ps真的有这种情况,答辩验收的时候几个人在讲台 ...

  3. ArcGIS API for JavaScript 4.2学习笔记[11] 官方第五章Popups(弹窗)概览与解释

    直接跳过第三第四章了,第三章Layer和第四章可视化,怎么说呢,Layer是组织数据的,是Map的属性之一.可视化属于符号化编程,暂时不看. 第五章是对数据.结果的显示,类似于alert()..NET ...

  4. [UWP]了解IValueConverter

    1. 前言 IValueConverter是用于数据绑定的强大的武器,它用于Value在Binding Source和Binding Target之间的转换.本文将介绍IValueConverter的 ...

  5. UVA 11600 Masud Rana

    题目大意:有一个n个点的完全图,有些路上有妖怪.现在一个人从一号点出发,每天随机走向另一个点,消灭路上的妖怪,问平均几天后所有点之间存在没有妖怪的路径.点数≤30. 看到点这么少肯定状压,看见存不下肯 ...

  6. jQuery中$(function(){})与(function($){})(jQuery)、$(document).ready(function(){})等的区别详细讲解 ----转载

    1.(function($) {-})(jQuery); 1).原理: 这实际上是匿名函数,如下: function(arg){-} 这就定义了一个匿名函数,参数为arg 而调用函数时,是在函数后面写 ...

  7. redis中使用 check-and-set 操作实现乐观锁

    WATCH 命令可以为 Redis 事务提供 check-and-set (CAS)行为. 被 WATCH 的键会被监视,并会发觉这些键是否被改动过了. 如果有至少一个被监视的键在 EXEC 执行之前 ...

  8. 初学者福音——10个最佳APP开发入门在线学习网站

    根据Payscale的调查显示,现在的APP开发人员的年薪达到:$66,851.这也是为什么那么多初学的开发都想跻身到APP开发这行业的主要原因之一.每当你打开App Store时候,看着琳琅满目的A ...

  9. Oracle学习笔记_09_字符串相关函数

    二.参考资料 0.Oracle中的字符串类型及相关函数详解 1.ORACLE 字符串操作 2.oracle函数大全-字符串处理函数

  10. 一、JavaSE语言概述

    1.软件:系统软件 VS 应用软件 2.人与计算交互:使用计算机语言.图形化界面VS命令行. 3.语言的分类:第一代:机器语言 第二代:汇编语言 第三代语言:高级语言(面向过程-面向对象) 4.jav ...