UESTC1546 - Bracket Sequence(区间覆盖&&区间合并)

题目大意

给定一个括号序列,支持一下以下三种操作:

1、set l r c: 把区间 [l,r]内的所有元素全部改成 c(c是’(’或者’)’)
2、reverse l r: 把区间[l,r]内的所以元素全部取反
3、query l,r: 查询区间 [l,r] 括号序列是否合法

题解

把左括号当成-1,右括号当成1,如果括号序列合法,则区间和为0,并且任意前缀和会小于等于0,当然我们不需要判断所有的前缀和是否都小于等于0,只需要维护一个前缀和最大值即可,只要前缀和最大值小于等于0,并且区间和为0,括号序列就是合法的,为了处理方便还额外增加一个域,前缀和的最小值,在进行取反操作的时候会方便很多,另外要注意set和reverse两种操作的顺序,顺序不同,结果也就不同,如果是set操作,则之前所有的标记都失效了,直接清除即可,但是如果有 set标记则进行取反,否则进行异或标记的取反操作

代码:

#include<iostream>

#include<cstdio>

#include<cstring>

#include<algorithm>

using namespace std;

#define lson l,m,s<<1

#define rson m+1,r,s<<1|1

#define MAXN 100005

int setv[MAXN<<2],Xor[MAXN<<2],sumv[MAXN<<2],lmin[MAXN<<2],lmax[MAXN<<2];

char str[MAXN];

void PushUp(int s)

{

        sumv[s]=sumv[s<<1]+sumv[s<<1|1];

        lmax[s]=max(lmax[s<<1],sumv[s<<1]+lmax[s<<1|1]);

        lmin[s]=min(lmin[s<<1],sumv[s<<1]+lmin[s<<1|1]);

}

void Fxor(int s,int m)

{

        int temp;

        if(setv[s]!=0) {

                if(setv[s]==1)

                        setv[s]=-1;

                else

                        setv[s]=1;

                if(setv[s]==1) {

                        sumv[s]=m;

                        lmax[s]=m;

                        lmin[s]=0;

                } else {

                        sumv[s]=-m;

                        lmax[s]=0;

                        lmin[s]=-m;

                }

        } else {

                Xor[s]^=1;

                sumv[s]=-sumv[s];

                temp=lmax[s];

                lmax[s]=-lmin[s];

                lmin[s]=-temp;

        }

}

void PushDown(int s,int m)

{

        if(setv[s]!=0) {

                setv[s<<1]=setv[s<<1|1]=setv[s];

                Xor[s<<1]=Xor[s<<1|1]=0;

                if(setv[s]==1) {

                        sumv[s<<1]=(m-(m>>1));

                        sumv[s<<1|1]=(m>>1);

                        lmax[s<<1]=sumv[s<<1];

                        lmax[s<<1|1]=sumv[s<<1|1];

                        lmin[s<<1]=0;

                        lmin[s<<1|1]=0;



                } else {

                        sumv[s<<1]=-(m-(m>>1));

                        sumv[s<<1|1]=-(m>>1);

                        lmin[s<<1]=-sumv[s<<1];

                        lmin[s<<1|1]=-sumv[s<<1|1];

                        lmax[s<<1]=0;

                        lmax[s<<1|1]=0;

                }

                setv[s]=0;

        }

        if(Xor[s]) {

                Fxor(s<<1,m-(m>>1));

                Fxor(s<<1|1,(m>>1));

                Xor[s]=0;

        }

}

void build(int l,int r,int s)

{

        setv[s]=0;

        Xor[s]=0;

        if(l==r) {

                if(str[l]=='(')

                        sumv[s]=-1;

                else

                        sumv[s]=1;

                lmax[s]=(sumv[s]>0)?1:0;

                lmin[s]=(sumv[s]<0)?-1:0;

                return;

        }

        int m=(l+r)>>1;

        build(lson);

        build(rson);

        PushUp(s);

}

void update(int ql,int qr,int d,int l,int r,int s)

{

        if(ql<=l&&r<=qr) {

                if(d==-1) {

                        setv[s]=-1;

                        sumv[s]=-(r-l+1);

                        lmax[s]=0;

                        lmin[s]=sumv[s];

                        Xor[s]=0;

                } else if(d==1) {

                        setv[s]=1;

                        sumv[s]=r-l+1;

                        lmax[s]=sumv[s];

                        lmin[s]=0;

                        Xor[s]=0;

                } else

                        Fxor(s,r-l+1);

                return;

        }

        PushDown(s,r-l+1);

        int m=(l+r)>>1;

        if(ql<=m) update(ql,qr,d,lson);

        if(qr>m) update(ql,qr,d,rson);

        PushUp(s);

}

int  querya(int ql,int qr,int l,int r,int s)

{

        if(ql<=l&&r<=qr)

                return sumv[s];

        PushDown(s,r-l+1);

        int m=(l+r)>>1,ans=0;

        if(ql<=m) ans+=querya(ql,qr,lson);

        if(qr>m) ans+=querya(ql,qr,rson);

        return ans;

}

int queryb(int ql,int qr,int l,int r,int s)

{

        if(ql<=l&&r<=qr)

                return lmax[s];

        PushDown(s,r-l+1);

        int m=(l+r)>>1,ans;

        if(qr<=m) ans=queryb(ql,qr,lson);

        else if(ql>m) ans=queryb(ql,qr,rson);

        else

                ans=max(queryb(ql,qr,lson),querya(ql,qr,lson)+queryb(ql,qr,rson));

        return ans;

}

int main(void)

{

        int T,n,m,a,b,p=0;

        char op[1000],ch[100];

        scanf("%d",&T);

        while(T--) {

                printf("Case %d:\n",++p);

                scanf("%d%s%d",&n,str,&m);

                build(0,n-1,1);

                while(m--) {

                        scanf("%s",op);

                        if(op[0]=='s') {

                                scanf("%d%d%s",&a,&b,ch);

                                if(ch[0]=='(')

                                        update(a,b,-1,0,n-1,1);

                                else

                                        update(a,b,1,0,n-1,1);

                        } else if(op[0]=='r') {

                                scanf("%d%d",&a,&b);

                                update(a,b,2,0,n-1,1);

                        } else {

                                scanf("%d%d",&a,&b);

                                if(!querya(a,b,0,n-1,1)&&!queryb(a,b,0,n-1,1))

                                        printf("YES\n");

                                else

                                        printf("NO\n");

                        }

                }

                printf("\n");

        }

        return 0;

}

你可能感兴趣的:(sequence)