UESTC 1546 Bracket Sequence 线段树成段更新

题意:给定一个括号序列,可以对它进行set,对把一定范围内的括号变成某一种括号,reverse把左右括号互换,query一定范围内的括号序列是否合法。

做法:一开始的想法,节点记录未匹配的左右括号数,然后进行操作,因为小看了reverse操作(本来以为简单的把左右括号的值改一下就好了,可是...),WA。

然后百度大神,重要发现了一个好算法。

造成一我错 的原因是无法准确找的无法配对的右括号。造成右括号无法配对的原因是,右括号没有足够的最括号,所以,大神把左括号设为1,右括号为-1,这样从左到右计算,节点中值的最小值,这个最小值为0就可能完全匹配,但不一定(只是解决了右括号问题),而且再也不怕reverse了


				        #include<cstdio>   
#include<cstring>   
#define left l,m,x<<1   
#define right m+1,r,x<<1|1   
const int LMT=100003;   
int cov[LMT<<2],ox[LMT<<2],sum[LMT<<2],mxsum[LMT<<2],misum[LMT<<2];   
char sec[LMT];   
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 ope(int op,int l,int r,int x)   
{   
    cov[x]=op;   
    mxsum[x]=op==1?r-l+1:0;   
    misum[x]=op==-1?-r+l-1:0;   
    sum[x]=(r-l+1)*op;   
    ox[x]=0;   
}   
void fox(int x)   
{   
    if(cov[x])   
    {   
        cov[x]*=-1;   
        sum[x]*=-1;   
        ox[x]=0;   
    }   
    else  
    {   
        ox[x]^=1;   
        sum[x]*=-1;   
    }   
    int t=mxsum[x];   
    mxsum[x]=-misum[x];   
    misum[x]=-t;   
}   
void cut(int l,int r,int x)   
{   
    int m=(l+r)>>1;   
    if(cov[x])   
    {   
        ope(cov[x],left);   
        ope(cov[x],right);   
        cov[x]=0;   
    }   
    if(ox[x])   
    {   
        fox(x<<1);fox(x<<1|1);   
        ox[x]=0;   
    }   
}   
void pushup(int x)   
{   
    sum[x]=sum[x<<1]+sum[x<<1|1];   
    misum[x]=min(misum[x<<1],sum[x<<1]+misum[x<<1|1]);   
    mxsum[x]=max(mxsum[x<<1],mxsum[x<<1|1]+sum[x<<1]);   
    /*******  
    MAXsum其实只是为了在翻转的时候用翻转的时候,以前不相和的括号就会相合,  
    这里的maxsum[x<<1|1]+sum[x<<1]提前做了这一步。  
    ****/  
}   
void update(int op,int L,int R,int l,int r,int x)   
{   
    if(L<=l&&r<=R)   
    {   
        if(op==-1)   
        {   
            ope(-1,l,r,x);   
            ox[x]=0;   
        }   
        if(op==1)   
        {   
            ope(1,l,r,x);   
            ox[x]=0;   
        }   
        if(op==2)fox(x);   
        return;   
    }   
    cut(l,r,x);   
    int m=(l+r)>>1;   
    if(L<=m)update(op,L,R,left);   
    if(R>m)update(op,L,R,right);   
    pushup(x);   
}   
void query(int &mi,int &all,int L,int R,int l,int r,int x)   
{   
    if(L<=l&&r<=R)   
    {   
        mi=misum[x];   
        all=sum[x];   
        return;   
    }   
    cut(l,r,x);   
    int m=(l+r)>>1,mi1=0,mi2=0,al1=0,al2=0;   
    if(L<=m)query(mi1,al1,L,R,left);   
    if(R>m)query(mi2,al2,L,R,right);   
    all=al1+al2;   
    mi=min(mi1,al1+mi2);   
}   
void init()   
{   
    memset(cov,0,sizeof(cov));   
    memset(ox,0,sizeof(ox));   
    memset(sum,0,sizeof(sum));   
    memset(misum,0,sizeof(misum));   
    memset(mxsum,0,sizeof(mxsum));   
}   
int main(void)   
{   
    int i,n,T,m,l,r,all,mi,I=1;   
    char ord[10],op;   
    scanf("%d",&T);   
    while(T--)   
    {   
        init();   
        scanf("%d%s",&n,sec);   
        for(i=0;sec[i];i++)   
        {   
            if(sec[i]=='(')   
                update(1,i,i,0,n-1,1);   
            else update(-1,i,i,0,n-1,1);   
        }   
        scanf("%d",&m);   
        printf("Case %d:\n",I++);   
        while(m--)   
        {   
            scanf("%s",ord);   
            if(!strcmp(ord,"query"))   
            {   
                scanf("%d%d",&l,&r);   
                mi=all=0;   
                query(mi,all,l,r,0,n-1,1);   
                if(mi==0&&all==0)puts("YES");   
                else puts("NO");   
            }   
            if(!strcmp(ord,"set"))   
            {   
                scanf("%d%d",&l,&r);   
                op=getchar();   
                while(op!='('&&op!=')')op=getchar();   
                if(op=='(')update(1,l,r,0,n-1,1);   
                else update(-1,l,r,0,n-1,1);   
            }   
            if(!strcmp(ord,"reverse"))   
            {   
                scanf("%d%d",&l,&r);   
                update(2,l,r,0,n-1,1);   
            }   
        }
		printf("\n");
    }   
            return 0;   
}  		


你可能感兴趣的:(UESTC 1546 Bracket Sequence 线段树成段更新)