UESTC 1546(线段树,成段更新,区间合并)

这个题有一点非常重要,就是任意一个非法的序列,我们在它的左边添加若干个"(",右边添加若干个")",那么一定能够变成一个合法的序列。

在这里就不证明了,比如"()))((",我们在它的左边添加两个"(",右边两个")",序列变成"((()))(())",就成了一个合法的序列了!

因此在每一个区间,我们记录它缺少的左括号数needl,缺少的右括号数needr,那么区间合并的问题就解决了。

这个题还有一个反号操作,因此我们还要记录每个区间反号以后缺少的左括号数tneedl,缺少的右括号数tneedr。

reverse的时候交换一下这两个值就行了。


#include<iostream>  
#include<cstdio>  
#include<cstring>  
using namespace std;  
#define lc l,m,index<<1  
#define rc m+1,r,index<<1|1  
#define N 200005  
struct node  
{  
    int set,rev;  
    int needl,needr;  
    int tneedl,tneedr;  
}seg[N<<2];  
int n,q;  
char str[N];  
void fset(int l,int r,int index,int flag)  
{  
    seg[index].set=flag;  
    seg[index].rev=0;  
    if(flag==1)//左括号  
    {  
        seg[index].needl=seg[index].tneedr=0;  
        seg[index].needr=seg[index].tneedl=r-l+1;  
    }  
    else//右括号  
    {  
        seg[index].needl=seg[index].tneedr=r-l+1;  
        seg[index].needr=seg[index].tneedl=0;  
    }  
}  
void frev(int l,int r,int index)  
{  
    seg[index].rev^=1;  
    swap(seg[index].needl,seg[index].tneedl);  
    swap(seg[index].needr,seg[index].tneedr);  
}  
void pushup(int l,int r,int index)  
{  
    node& father=seg[index];  
    node& lson=seg[index<<1];  
    node& rson=seg[index<<1|1];  
    father.needl=lson.needl;  
    father.needr=rson.needr;  
    if(lson.needr>rson.needl)father.needr+=lson.needr-rson.needl;  
    else father.needl+=rson.needl-lson.needr;  
    father.tneedl=lson.tneedl;  
    father.tneedr=rson.tneedr;  
    if(lson.tneedr>rson.tneedl)father.tneedr+=lson.tneedr-rson.tneedl;  
    else father.tneedl+=rson.tneedl-lson.tneedr;  
}  
void pushdown(int l,int r,int index)  
{  
    int m=(l+r)>>1;  
    node& father=seg[index];  
    node& lson=seg[index<<1];  
    node& rson=seg[index<<1|1];  
    if(father.set)  
    {  
        fset(lc,father.set);  
        fset(rc,father.set);  
        father.set=0;  
    }  
    if(father.rev)  
    {  
        frev(lc);  
        frev(rc);  
        father.rev=0;  
    }  
}  
void build(int l,int r,int index)  
{  
    seg[index].set=seg[index].rev=0;  
    if(l==r)  
    {  
        if(str[l]=='(')  
        {  
            seg[index].needl=seg[index].tneedr=0;  
            seg[index].needr=seg[index].tneedl=1;  
        }  
        else  
        {  
            seg[index].needl=seg[index].tneedr=1;  
            seg[index].needr=seg[index].tneedl=0;  
        }  
        return;  
    }  
    int m=(l+r)>>1;  
    build(lc);  
    build(rc);  
    pushup(l,r,index);  
}  
void updataset(int L,int R,int flag,int l,int r,int index)  
{  
    if(L==l&&R==r)  
    {  
        fset(l,r,index,flag);  
        return;  
    }  
    pushdown(l,r,index);  
    int m=(l+r)>>1;  
    if(R<=m)updataset(L,R,flag,lc);  
    else if(L>m)updataset(L,R,flag,rc);  
    else  
    {  
        updataset(L,m,flag,lc);  
        updataset(m+1,R,flag,rc);  
    }  
    pushup(l,r,index);  
}  
void updatarev(int L,int R,int l,int r,int index)  
{  
    if(L==l&&R==r)  
    {  
        frev(l,r,index);  
        return;  
    }  
    pushdown(l,r,index);  
    int m=(l+r)>>1;  
    if(R<=m)updatarev(L,R,lc);  
    else if(L>m)updatarev(L,R,rc);  
    else  
    {  
        updatarev(L,m,lc);  
        updatarev(m+1,R,rc);  
    }  
    pushup(l,r,index);  
}  
node query(int L,int R,int l,int r,int index)  
{  
    if(L==l&&R==r)return seg[index];  
    pushdown(l,r,index);  
    int m=(l+r)>>1;  
    if(R<=m)return query(L,R,lc);  
    else if(L>m)return query(L,R,rc);  
    else  
    {  
        node lson,rson,father;  
        lson=query(L,m,lc);  
        rson=query(m+1,R,rc);  
        father.needl=lson.needl;  
        father.needr=rson.needr;  
        if(lson.needr>rson.needl)father.needr+=lson.needr-rson.needl;  
        else father.needl+=rson.needl-lson.needr;  
        return father;  
    }  
}  
int main()  
{  
    int t,tcase=1,a,b;  
    node ans;  
    char op[25],temp[25];  
    scanf("%d",&t);  
    while(t--)  
    {  
        printf("Case %d:\n",tcase++);  
        scanf("%d%s%d",&n,str,&q);  
        build(0,n-1,1);  
        while(q--)  
        {  
            scanf("%s%d%d",op,&a,&b);  
            if(op[0]=='q')  
            {  
                ans=query(a,b,0,n-1,1);  
                if(ans.needl==0&&ans.needr==0)printf("YES\n");  
                else printf("NO\n");  
            }  
            else if(op[0]=='s')  
            {  
                scanf("%s",temp);  
                if(temp[0]=='(')updataset(a,b,1,0,n-1,1);  
                else updataset(a,b,2,0,n-1,1);  
            }  
            else updatarev(a,b,0,n-1,1);  
        }  
        printf("\n");  
    }  
    return 0;  
}   


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值