传送门

题意简述:

给一个括号序列,要求支持:

  • 区间覆盖
  • 区间取负
  • 区间翻转
  • 查询把一个区间改成合法括号序列最少改几位

思路:

先考虑静态的时候如何维护答案。

显然把所有合法的都删掉之后序列长这样:

))...)))(((...(())...)))(((...(())...)))(((...((

于是可以给(((赋值成−1-1−1,)))赋值成111,这样只用维护前缀最大值aaa和后缀最小值bbb。

然后就可以知道答案是⌊a+12⌋+⌊−b+12⌋\left\lfloor\frac{a+1}2\right\rfloor+\left\lfloor\frac{-b+1}2\right\rfloor⌊2a+1​⌋+⌊2−b+1​⌋,然后由于a+b=a+b=a+b=这段区间的和,因此实际上只用维护aaa。

于是用一个fhqtreapfhq_treapfhqt​reap来支持上述修改即可。

代码:

#include<bits/stdc++.h>
#define fi first
#define se second
#define ri register int
#define gc getchar
using namespace std;
inline int read(){
    int ans=0;
    char ch=gc();
    while(!isdigit(ch))ch=gc();
    while(isdigit(ch))ans=((ans<<2)+ans<<1)+(ch^48),ch=gc();
    return ans;
}
typedef pair<int,int> pii;
const int N=1e5+5;
int n,m;
char s[N];
inline unsigned int randd(){
    static unsigned int x=23333;
    return x^=x<<13,x^=x>>17,x^=x<<5;
}
namespace fhq{
    #define lc son[p][0]
    #define rc son[p][1]
    int siz[N],son[N][2],rd[N],cov[N],ls[N],rs[N],sum[N],val[N],rt=0,tot=0;
    bool rev[N],inv[N];
    inline void pushup(int p){
        ls[p]=max(ls[lc],sum[lc]+val[p]+ls[rc]);
        rs[p]=max(rs[rc],sum[rc]+val[p]+rs[lc]);
        siz[p]=siz[lc]+1+siz[rc];
        sum[p]=sum[lc]+val[p]+sum[rc];
    }
    inline void pushcov(int p,int v){ls[p]=rs[p]=max((int)(inv[p]=rev[p]=0),sum[p]=((cov[p]=val[p]=v)*siz[p]));}
    inline void pushrev(int p){rev[p]^=1,swap(ls[p],rs[p]),swap(lc,rc);}
    inline void pushinv(int p){inv[p]^=1,ls[p]-=sum[p],rs[p]-=sum[p],swap(ls[p],rs[p]),val[p]=-val[p],sum[p]=-sum[p];}
    inline void pushdown(int p){
        if(cov[p])pushcov(lc,cov[p]),pushcov(rc,cov[p]),cov[p]=0;
        if(rev[p])pushrev(lc),pushrev(rc),rev[p]=0;
        if(inv[p])pushinv(lc),pushinv(rc),inv[p]=0;
    }
    inline int merge(int a,int b){
        if(!a||!b)return a+b;
        pushdown(a),pushdown(b);
        if(rd[a]<rd[b])return son[a][1]=merge(son[a][1],b),pushup(a),a;
        return son[b][0]=merge(a,son[b][0]),pushup(b),b;
    }
    inline pii split(int p,int k){
        if(!p)return pii(0,0);
        pii tmp;
        pushdown(p);
        if(siz[lc]>=k)return tmp=split(lc,k),lc=tmp.se,pushup(p),pii(tmp.fi,p);
        return tmp=split(rc,k-siz[lc]-1),rc=tmp.fi,pushup(p),pii(p,tmp.se);
    }
    inline void build(int&p,int l,int r){
        if(l>r)return;
        int mid=l+r>>1;
        p=++tot;
        val[p]=sum[p]=s[mid]=='('?-1:1,rd[p]=randd();
        if(l==r){ls[p]=rs[p]=max(0,val[p]),siz[p]=1;return;}
        build(lc,l,mid-1),build(rc,mid+1,r),pushup(p);
    }
    inline void cover(int l,int r,int v){
        pii x=split(rt,l-1),y=split(x.se,r-l+1);
        pushcov(y.fi,v),rt=merge(x.fi,merge(y.fi,y.se));
    }
    inline void reverse(int l,int r){
        pii x=split(rt,l-1),y=split(x.se,r-l+1);
        pushrev(y.fi),rt=merge(x.fi,merge(y.fi,y.se));
    }
    inline void invert(int l,int r){
        pii x=split(rt,l-1),y=split(x.se,r-l+1);
        pushinv(y.fi),rt=merge(x.fi,merge(y.fi,y.se));
    }
    inline void query(int l,int r){
        pii x=split(rt,l-1),y=split(x.se,r-l+1);
        cout<<((ls[y.fi]+1)>>1)+((ls[y.fi]-sum[y.fi]+1)>>1)<<'\n',rt=merge(x.fi,merge(y.fi,y.se));
    }
    #undef lc
    #undef rc
}
int main(){
    n=read(),m=read(),scanf("%s",s+1);
    fhq::build(fhq::rt,1,n);
    char s[10],t[2];
    for(ri l,r;m;--m){
        scanf("%s",s),l=read(),r=read();
        if(s[0]=='R'){
            scanf("%s",t);
            fhq::cover(l,r,t[0]=='('?-1:1);
        }
        if(s[0]=='Q')fhq::query(l,r);
        if(s[0]=='I')fhq::invert(l,r);
        if(s[0]=='S')fhq::reverse(l,r);
    }
    return 0;
}

2019.03.25 bzoj2329: [HNOI2011]括号修复(fhq_treap)的更多相关文章

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

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

  2. BZOJ2329 [HNOI2011]括号修复

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

  3. BZOJ2329 HNOI2011 括号修复 splay+贪心

    找平衡树练习题的时候发现了这道神题,可以说这道题是近几年单考splay的巅峰之作了. 题目大意:给出括号序列,实现区间翻转,区间反转和区间更改.查询区间最少要用几次才能改成合法序列. 分析: 首先我们 ...

  4. BZOJ2329: [HNOI2011]括号修复(Splay)

    解题思路: Replace.Swap.Invert都可以使用Splay完美解决(只需要解决一下标记冲突就好了). 最后只需要统计左右括号冲突就好了. 相当于动态统计最大前缀合和最小后缀和. 因为支持翻 ...

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

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

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

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

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

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

  8. [2019.03.25]Linux中的查找

    TMUX天下第一 全世界所有用CLI Linux的人都应该用TMUX,我爱它! ======================== 以下是正文 ======================== Linu ...

  9. 【BZOJ2329】括号修复(Splay)

    [BZOJ2329]括号修复(Splay) 题面 BZOJ 洛谷 题解 本来想着用线段树来写 但是有一个区间翻转 所以不能用线段树了,就只能用平衡树 然后直接\(Splay\)就好了 注意一下几个标记 ...

随机推荐

  1. lnmp之Nginx配置https加密访问

    配置lnmp之Nginx网站支持https加密访问 注: 1. 这里拿购买的(pxsnx.pxjy.com)证书来做样例 证书文件共有三个---> (pxsnxg.pxjy.com_ca.crt ...

  2. 20175213《Java程序设计》实验二Java面向对象程序设计实验报告

    实验内容 1.初步掌握单元测试和TDD 2.理解并掌握面向对象三要素:封装,继承,多态 3.初步掌握UML建模 4.熟悉S.O.L.I.D原则 5.了解设计模式 知识总结 1.伪代码 2.产品代码: ...

  3. python学习Day12 函数的默认值、三元表达式、函数对象(函数名)的应用场景、名称空间与作用域

    复习 1.字符串的比较: -- 按照从左往右比较每一个字符,通过字符对应的ascii进行比较 2. 函数的参数 : 1)实参与形参:       -- 形参:在函数定义时()中出现的参数       ...

  4. nginx 做数据仓库时,location 404 Not Found,发现找不到要用的数据报:Not Found

    背景:  获得远程机器某个目录下的数据文件 方案:使用Nginx配置 1./home/ftp/www/ 下面有images 文件夹,为了访问images下面文件,配置Nginx如下: location ...

  5. 安装oracle [INS-32025] 所选安装与指定 Oracle 主目录中已安装的软件冲突” 的问题

    删除C:\Program Files (x86)\Oracle\Inventory\下的Oracle文件夹即可解决问题

  6. CAS 无锁队列

    队列是常用的数据结构,采用的FIFO(first in firstout)原则,新元素(等待进入队列的元素)总是被插入到尾部,而读取的时候总是从头部开始读取.在计算中队列一般用来做排队(如线程池的等待 ...

  7. c# webBrowser 转图片

    class NativeMethods { [ComImport] [Guid("0000010D-0000-0000-C000-000000000046")] [Interfac ...

  8. hashCode 与 equals

    面试官可能会问你:“你重写过 hashcode 和 equals 么,为什么重写equals时必须重写hashCode方法?”   hashCode()介绍 hashCode() 的作用是获取哈希码, ...

  9. 使用scrapy中xpath选择器的一个坑点

    情景如下: 一个网页下有一个ul,这个ur下有125个li标签,每个li标签下有我们想要的 url 字段(每个 url 是唯一的)和 price 字段,我们现在要访问每个li下的url并在生成的请求中 ...

  10. 【Spring源码解析】—— 依赖注入结合SpringMVC Demo-xml配置理解

    在IOC容器初始化的梳理之后,对依赖注入做一个总结,就是bean实例化的过程,bean的定义有两种方式,一种是xml文件配置,一种是注解,这里是对xml配置文件的依赖注入的介绍,后续对bean与该部分 ...