spoj 61 Brackets(线段树)

来源:互联网 发布:谢朝阳 云计算 编辑:程序博客网 时间:2024/05/08 16:11

题意:给出一个括号序列,有两种操作,一种是将括号取反,一种是查询当前的括号序列是否正确。

思路:还是个挺简单的问题吧,之前做过类似的,做起来就轻松多了。线段树的每个结点维护两个值:这个区间剩余没有匹配的左括号的数量,这个区间剩余的没有匹配的右括号数量。合并的时候只可能是左区间的左括号和右区间的右括号匹配,把匹配掉的减去就好了。

代码:

#include<iostream>#include<cstdio>#include<cstring>#include<string>#include<algorithm>#include<map>#include<queue>#include<stack>#include<cmath>#include<vector>#define inf 0x3f3f3f3f#define Inf 0x3FFFFFFFFFFFFFFFLL#define eps 1e-9#define pi acos(-1.0)using namespace std;typedef long long ll;const int maxn=30000+10;int lf[maxn<<2],rn[maxn<<2];char str[maxn];void PushUp(int rt){    int tmp=min(lf[rt<<1],rn[rt<<1|1]);    lf[rt]=lf[rt<<1]+lf[rt<<1|1]-tmp;    rn[rt]=rn[rt<<1]+rn[rt<<1|1]-tmp;}void build(int l,int r,int rt){    if(l==r)    {        lf[rt]=rn[rt]=0;        if(str[l]=='(') lf[rt]=1;        else rn[rt]=1;        return ;    }    int m=(l+r)>>1;    build(l,m,rt<<1);    build(m+1,r,rt<<1|1);    PushUp(rt);}void Update(int p,int l,int r,int rt){    if(l==r)    {        lf[rt]^=1;        rn[rt]^=1;        return ;    }    int m=(l+r)>>1;    if(m>=p) Update(p,l,m,rt<<1);    else Update(p,m+1,r,rt<<1|1);    PushUp(rt);}int main(){    //freopen("in.txt","r",stdin);    //freopen("out.txt","w",stdout);    for(int tcase=1;tcase<=10;++tcase)    {        int n;        scanf("%d",&n);        scanf("%s",str+1);        build(1,n,1);        int q,x;        scanf("%d",&q);        printf("Test %d:\n",tcase);        while(q--)        {            scanf("%d",&x);            if(x>0) Update(x,1,n,1);            else            {                if(lf[1]||rn[1]) puts("NO");                else puts("YES");            }        }    }    return 0;}

0 0