• bzoj2329: [HNOI2011]括号修复(fhq treap)


    http://www.lydsy.com/JudgeOnline/problem.php?id=2329

    需要改变的括号序列一定长这样 :)))(((

    最少改变次数= 多余的‘)’/2 【上取整】 + 多余的‘(’ /2 【上取整】

    把 ‘)’ 看做1,‘(’ 看做-1

    那么最少改变次数=最大前缀和/2 【上取整】+ 最小后缀和/2 【上取整】

    覆盖标记的优先级高于翻转标记和取反标记

    即下放覆盖标记时,同时清空翻转标记和取反标记

    且先下放覆盖标记

    翻转:

    最大前缀和 和 最大后缀和 交换

    最小前缀和 和 最小后缀和 交换

    取反:

    最大前缀和 和 最小前缀和 交换,同时取反

    最大后缀和 和 最小后缀和 交换,同时取反

    最大XX和的下界为0,最小XX和的上界为0

    因为最大XX和实际是多余的‘)’数量

    最小XX和的相反数实际是多余的‘(’数量

    数量不能为负数

    注意点:

    1、增加了首尾两个虚拟节点后,数组要多开2

    2、平衡树每个节点由三部分组成,左子树、自己、右子树,打取反标记的时候不要忘记给自己取反

    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
     
    using namespace std;
     
    #define N 100003
     
    char ss[N];
    int a[N];
     
    int root,tot;
     
    int st[N];
     
    bool rev[N],inv[N];
    int tag[N];
    int pre[N],suf[N];
    int sum[N];
    int pri[N],val[N];
     
    int siz[N],ch[N][2];
     
    int tmp;
     
    void read(int &x)
    {
        x=0; char c=getchar();
        while(!isdigit(c)) c=getchar();
        while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); }
    }
     
    inline int &max(int &a,int &b) { return a>b ? a : b; }
    inline int &min(int &a,int &b) { return a<b ? a : b; }
     
    void update(int x)
    {
        int l=ch[x][0],r=ch[x][1];
        siz[x]=siz[l]+siz[r]+1;
        sum[x]=sum[l]+sum[r]+val[x];
        pre[x]=max(pre[l],sum[l]+pre[r]+val[x]);
        pre[x]=max(pre[x],sum[l]+val[x]);
        suf[x]=max(suf[r],sum[r]+suf[l]+val[x]);
        suf[x]=max(suf[x],sum[r]+val[x]);
    }
     
    int newnode(int v)
    {
        val[++tot]=sum[tot]=v;
        pre[tot]=suf[tot]=max(0,val[tot]);
        sum[tot]=val[tot];
        siz[tot]=1;
        pri[tot]=rand();
        return tot;
    }
     
    int build(int l,int r)
    {
        int top=0; int last,now;
        for(int i=l;i<=r;++i)
        {
            now=newnode(a[i]);
            last=0;
            while(top && pri[now]<pri[st[top]])
            {
                update(st[top]);
                last=st[top--];
            }
            if(top) ch[st[top]][1]=now;
            ch[now][0]=last; 
            st[++top]=now;
        }
        while(top) update(st[top--]);
        return st[1];
    }
     
    void down(int x)
    {
        int l=ch[x][0],r=ch[x][1];
        if(tag[x])
        {
            if(l)
            {
                val[l]=tag[x];
                sum[l]=tag[x]*siz[l];
                pre[l]=suf[l]=max(0,sum[l]);
                rev[l]=inv[l]=false;
                tag[l]=tag[x];
            }
            if(r)
            {
                val[r]=tag[x];
                sum[r]=tag[x]*siz[r];
                pre[r]=suf[r]=max(0,sum[r]);
                rev[r]=inv[r]=false;
                tag[r]=tag[x];
            }
            tag[x]=0;
        }
        if(rev[x])
        {
            if(l)
            {   
                swap(pre[l],suf[l]);
                swap(ch[l][0],ch[l][1]);
                rev[l]^=1;
            }
            if(r)
            {   
                swap(pre[r],suf[r]);
                swap(ch[r][0],ch[r][1]);
                rev[r]^=1;
            }
            rev[x]^=1;
        }
        if(inv[x])
        {
            if(l)
            {
                tmp=pre[l];
                pre[l]=max(0,-(sum[l]-suf[l]));
                suf[l]=max(0,-(sum[l]-tmp));
                sum[l]=pre[l]+min(0,-sum[l]-pre[l]);
                val[l]=-val[l];
                inv[l]^=1;
            }
            if(r)
            {
                tmp=pre[r];
                pre[r]=max(0,-(sum[r]-suf[r]));
                suf[r]=max(0,-(sum[r]-tmp));
                sum[r]=pre[r]+min(0,-sum[r]-pre[r]);
                val[r]=-val[r];
                inv[r]^=1;
            }
            inv[x]^=1;
        }
    }
     
    void split(int now,int k,int &x,int &y)
    {
        if(!now) x=y=0;
        else
        {
            down(now);
            if(k<=siz[ch[now][0]])
            {
                y=now;
                split(ch[now][0],k,x,ch[now][0]);
            }
            else
            {
                x=now;
                split(ch[now][1],k-siz[ch[now][0]]-1,ch[now][1],y);
            }
            update(now);
        }       
    }
     
    int merge(int x,int y)
    {
        if(x) down(x);
        if(y) down(y);
        if(!x || !y) return x+y;
        if(pri[x]<pri[y])
        {
            ch[x][1]=merge(ch[x][1],y);
            update(x);
            return x;
        }
        else
        {
            ch[y][0]=merge(x,ch[y][0]);
            update(y);
            return y;
        }
    }
         
     
    int main()
    {
        int n,m;
        read(n); read(m);
        scanf("%s",ss+2);
        for(int i=2;i<=n+1;++i) 
            if(ss[i]==')') a[i]=1;
            else a[i]=-1;
        root=build(1,n+2);
        int l,r; char s[10],cc[3];
        int a,b,c,d,e;
        while(m--)
        {
            scanf("%s",s);
            read(l); read(r);
            l++; r++;
            split(root,r,a,b);
            split(a,l-1,c,d);
            if(s[0]=='R')
            {
                scanf("%s",cc);
                e= cc[0]==')' ? 1 : -1;
                tag[d]=e;
                val[d]=e;
                sum[d]=e*siz[d];
                pre[d]=suf[d]=max(0,sum[d]);
                rev[d]=inv[d]=false;
            }
            else if(s[0]=='S')
            {
                rev[d]=true;
                swap(ch[d][0],ch[d][1]);
                swap(pre[d],suf[d]);
            }
            else if(s[0]=='I')
            {
                inv[d]=true;
                tmp=pre[d];
                pre[d]=max(0,-(sum[d]-suf[d]));
                suf[d]=max(0,-(sum[d]-tmp));
                sum[d]=pre[d]+min(0,-sum[d]-pre[d]);
                val[d]=-val[d];
            }
            else printf("%d
    ",(pre[d]+1)/2+(-sum[d]+pre[d]+1)/2);
            root=merge(merge(c,d),b);
        }
    }

    2329: [HNOI2011]括号修复

    Time Limit: 40 Sec  Memory Limit: 128 MB
    Submit: 1229  Solved: 580
    [Submit][Status][Discuss]

    Description

  • 相关阅读:
    Java虚拟机及运行时数据区
    Math小记
    利用BitMap进行大数据排序去重
    Java直接内存与堆内存
    【分布式搜索引擎】Elasticsearch之安装Elasticsearch可视化平台Kibana
    【分布式搜索引擎】Elasticsearch之如何安装Elasticsearch
    【微信错误】{"errcode":"40013","errmsg":"invalid appid hint: [mackRA06203114]","success":false}
    【Java】理解ClassNotFoundException与NoClassDefFoundError的区别
    【Spring Boot】Spring Boot之使用AOP实现数据库多数据源自动切换
    【异常】The dependencies of some of the beans in the application context form a cycle
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/8401366.html
Copyright © 2020-2023  润新知