zoukankan      html  css  js  c++  java
  • BZOJ2329: [HNOI2011]括号修复

    【传送门:BZOJ2329


    简要题意:

      给出一个长度为n的括号序列,有q个操作,4种操作:

      Query l r求出最少的步数,每步可以改变一个括号,将l到r的括号序列变为一一配对(也就是左括号在右边总有一个右括号与之对应)

      Invert l r将l到r中的左括号变成右括号,右括号变成左括号

      Swap l r将l到r的序列翻转

      Replace l r c将l到r的括号都变成c


    题解:

      SPLAY

      对于一个括号序列,将左括号看成1,右括号看成-1

      最少的步数为一段序列中:(最小前缀和的绝对值+1)/2+(最大后缀和+1)/2

      这样子就要维护最小前缀和和最大后缀和,还要维护最小后缀和和最大前缀和(为了方便修改)

      但是这道题的下放标记要注意顺序

      首先swap操作其实对于其他两个是没有影响的,所以我们只要考虑Invert和Replace操作的顺序

      如果当前需要对x点进行Invert时,如果x的Replace标记为不为0(代表需要改变),则不需要将Invert的标记变true,直接将Replace标记变为相反数

      如果当前需要对x点进行Replace时,直接将Invert变为false,直接覆盖掉


    参考代码:

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    struct node
    {
        int son[2],f,c,s,d;
        int ln,rn,lm,rm,cg;
        bool fz,zf;
    }tr[110000];int len,root;
    void fanzhuan(int x)
    {
        tr[x].fz=false;
        swap(tr[x].son[0],tr[x].son[1]);
        int lc=tr[x].son[0],rc=tr[x].son[1];
        if(lc!=0)
        {
            swap(tr[lc].ln,tr[lc].rn);
            swap(tr[lc].lm,tr[lc].rm);
            tr[lc].fz^=1;
        }
        if(rc!=0)
        {    
            swap(tr[rc].ln,tr[rc].rn);
            swap(tr[rc].lm,tr[rc].rm);
            tr[rc].fz^=1;
        }
    }
    void zhuanfan(int x)
    {
        tr[x].zf=false;
        int lc=tr[x].son[0],rc=tr[x].son[1];
        if(lc!=0)
        {
            tr[lc].ln=-tr[lc].ln;tr[lc].lm=-tr[lc].lm;
            swap(tr[lc].ln,tr[lc].lm);
            tr[lc].rn=-tr[lc].rn;tr[lc].rm=-tr[lc].rm;
            swap(tr[lc].rn,tr[lc].rm);
            tr[lc].s=-tr[lc].s;tr[lc].d=-tr[lc].d;
            if(tr[lc].cg==0) tr[lc].zf^=1;
            else tr[lc].cg=-tr[lc].cg;
        }
        if(rc!=0)
        {
            tr[rc].ln=-tr[rc].ln;tr[rc].lm=-tr[rc].lm;
            swap(tr[rc].ln,tr[rc].lm);
            tr[rc].rn=-tr[rc].rn;tr[rc].rm=-tr[rc].rm;
            swap(tr[rc].rn,tr[rc].rm);
            tr[rc].s=-tr[rc].s;tr[rc].d=-tr[rc].d;
            if(tr[rc].cg==0) tr[rc].zf^=1;
            else tr[rc].cg=-tr[rc].cg;
        }
    }
    void change(int x)
    {
        int lc=tr[x].son[0],rc=tr[x].son[1];
        if(lc!=0)
        {
            if(tr[x].cg==-1)
            {
                tr[lc].ln=tr[lc].rn=-tr[lc].c;
                tr[lc].lm=tr[lc].rm=0;
                tr[lc].s=-tr[lc].c;tr[lc].d=-1;
            }
            else
            {
                tr[lc].ln=tr[lc].rn=0;
                tr[lc].lm=tr[lc].rm=tr[lc].c;
                tr[lc].s=tr[lc].c;tr[lc].d=1;
            }
            tr[lc].cg=tr[x].cg;tr[x].zf=false;
        }
        if(rc!=0)
        {
            if(tr[x].cg==-1)
            {
                tr[rc].ln=tr[rc].rn=-tr[rc].c;
                tr[rc].lm=tr[rc].rm=0;
                tr[rc].s=-tr[rc].c;tr[rc].d=-1;
            }
            else
            {
                tr[rc].ln=tr[rc].rn=0;
                tr[rc].lm=tr[rc].rm=tr[rc].c;
                tr[rc].s=tr[rc].c;tr[rc].d=1;
            }
            tr[rc].cg=tr[x].cg;tr[x].zf=false;
        }
        tr[x].cg=0;
    }
    void update(int x)
    {
        int lc=tr[x].son[0],rc=tr[x].son[1];
        tr[x].c=tr[lc].c+tr[rc].c+1;
        tr[x].s=tr[lc].s+tr[rc].s+tr[x].d;
        tr[x].ln=min(tr[lc].s+tr[rc].ln+tr[x].d,tr[lc].ln);
        tr[x].lm=max(tr[lc].s+tr[rc].lm+tr[x].d,tr[lc].lm);
        tr[x].rn=min(tr[lc].rn+tr[rc].s+tr[x].d,tr[rc].rn);
        tr[x].rm=max(tr[lc].rm+tr[rc].s+tr[x].d,tr[rc].rm);
    }
    int a[110000];
    int bt(int l,int r)
    {
        if(l>r) return 0;
        int now=++len;int mid=(l+r)/2;
        tr[now].d=a[mid];
        tr[now].fz=tr[now].zf=false;tr[now].cg=0;
        tr[now].son[0]=bt(l,mid-1);tr[now].son[1]=bt(mid+1,r);
        int lc=tr[now].son[0],rc=tr[now].son[1];
        if(lc!=0) tr[lc].f=now;
        if(rc!=0) tr[rc].f=now;
        update(now);
        return now;
    }
    void rotate(int x,int w)
    {
        int f=tr[x].f,ff=tr[f].f;
        int r,R;
        r=tr[x].son[w];R=f;
        tr[R].son[1-w]=r;
        if(r!=0) tr[r].f=R;
        r=x;R=ff;
        if(tr[R].son[0]==f) tr[R].son[0]=r;
        else tr[R].son[1]=r;
        tr[r].f=R;
        r=f;R=x;
        tr[R].son[w]=r;
        tr[r].f=R;
        update(f);
        update(x);
    }
    int tmp[110000],s;
    void splay(int x,int rt)
    {
        int i=x;s=0;
        while(tr[i].f!=rt)
        {
            tmp[++s]=i;
            i=tr[i].f;
        }
        tmp[++s]=i;
        while(s!=0)
        {
            i=tmp[s--];
            if(tr[i].cg!=0) change(i);
            if(tr[i].fz==true) fanzhuan(i);
            if(tr[i].zf==true) zhuanfan(i);
        }
        while(tr[x].f!=rt)
        {
            int f=tr[x].f,ff=tr[f].f;
            if(ff==rt)
            {
                if(tr[f].son[0]==x) rotate(x,1);
                else rotate(x,0);
            }
            else
            {
                if(tr[f].son[0]==x&&tr[ff].son[0]==f){rotate(f,1);rotate(x,1);continue;}
                if(tr[f].son[1]==x&&tr[ff].son[0]==f){rotate(x,0);rotate(x,1);continue;}
                if(tr[f].son[0]==x&&tr[ff].son[1]==f){rotate(x,1);rotate(x,0);continue;}
                if(tr[f].son[1]==x&&tr[ff].son[1]==f){rotate(f,0);rotate(x,0);continue;}
            }
        }
        if(rt==0) root=x;
    }
    int finddizhi(int k)
    {
        int x=root;
        while(1)
        {
            if(tr[x].cg!=0) change(x);
            if(tr[x].fz==true) fanzhuan(x);
            if(tr[x].zf==true) zhuanfan(x);
            int lc=tr[x].son[0],rc=tr[x].son[1];
            if(k<=tr[lc].c) x=lc;
            else if(k>tr[lc].c+1){k-=tr[lc].c+1;x=rc;}
            else break;
        }
        return x;
    }
    void findmin(int l,int r)
    {
        int lc=finddizhi(l-1),rc=finddizhi(r+1);
        splay(lc,0);splay(rc,lc);
        int x=tr[rc].son[0];
        printf("%d
    ",(abs(tr[x].ln)+1)/2+(tr[x].rm+1)/2);
    }
    void zhuanfan_(int l,int r)
    {
        int lc=finddizhi(l-1);int rc=finddizhi(r+1);
        splay(lc,0);splay(rc,lc);
        int x=tr[rc].son[0];
        tr[x].ln=-tr[x].ln;tr[x].lm=-tr[x].lm;
        swap(tr[x].ln,tr[x].lm);
        tr[x].rn=-tr[x].rn;tr[x].rm=-tr[x].rm;
        swap(tr[x].rn,tr[x].rm);
        tr[x].s=-tr[x].s;tr[x].d=-tr[x].d;
        if(tr[x].cg==0) tr[x].zf^=1;
        else tr[x].cg=-tr[x].cg;
        splay(x,0);
    }
    void fanzhuan_(int l,int r)
    {
        int lc=finddizhi(l-1),rc=finddizhi(r+1);
        splay(lc,0);splay(rc,lc);
        int x=tr[rc].son[0];
        swap(tr[x].ln,tr[x].rn);
        swap(tr[x].lm,tr[x].rm);
        tr[x].fz^=1;
        splay(x,0);
    }
    void change_(int l,int r,int d)
    {
        int lc=finddizhi(l-1),rc=finddizhi(r+1);
        splay(lc,0);splay(rc,lc);
        int x=tr[rc].son[0];
        if(d==-1)
        {
            tr[x].ln=tr[x].rn=-tr[x].c;
            tr[x].lm=tr[x].rm=0;
            tr[x].s=-tr[x].c;tr[x].d=-1;
        }
        else
        {
            tr[x].ln=tr[x].rn=0;
            tr[x].lm=tr[x].rm=tr[x].c;
            tr[x].s=tr[x].c;tr[x].d=1;
        }
        tr[x].cg=d;tr[x].zf=false;
        splay(x,0);
    }
    char st[110000];
    int main()
    {
        int n,q;
        scanf("%d%d",&n,&q);
        scanf("%s",st+1);
        for(int i=1;i<=n;i++)
        {
            if(st[i]=='(') a[i+1]=1;
            else a[i+1]=-1;
        }
        len=0;root=bt(1,n+2);
        for(int i=1;i<=q;i++)
        {
            int l,r;
            scanf("%s%d%d",st+1,&l,&r);l++;r++;
            if(st[1]=='Q') findmin(l,r);
            if(st[1]=='I') zhuanfan_(l,r);
            if(st[1]=='S') fanzhuan_(l,r);
            if(st[1]=='R')
            {
                char c[2];
                scanf("%s",c+1);
                if(c[1]=='(') change_(l,r,1);
                else change_(l,r,-1);
            }
        }
        return 0;
    }

     

  • 相关阅读:
    《Windows编程循序渐进》——对话框应用程序2
    《Windows编程循序渐进》——对话框应用程序
    《Windows编程循序渐进》——建立MFC应用程序
    关于基类和子类构造函数的问题
    《Windows驱动开发技术详解》之分层驱动程序
    《Windows驱动开发技术详解》之驱动程序调用驱动程序——通过设备指针调用其他驱动程序
    《Windows驱动开发技术详解》之驱动程序调用驱动程序——以文件句柄形式调用其它驱动程序
    《Windows驱动开发技术详解》之定时器
    《Windows驱动开发技术详解》之自定义StartIO
    四种UNIX实现
  • 原文地址:https://www.cnblogs.com/Never-mind/p/8949310.html
Copyright © 2011-2022 走看看