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;
}

posted on 2013-06-03 00:56  仗剑奔走天涯  阅读(249)  评论(0编辑  收藏  举报

导航