牛客 Yet Another Bracket Sequence 线段树

题目链接

题意:给定括号序列,让后m次修改,对于每次修改回答括号序列是否合法。

可以先想想暴力怎么搞,从头枚举,记一个cnt,碰到 ( 就 cnt++ ,碰到 ) 就cnt-- ,如果碰到cnt < 0 的情况,或者最后 cnt != 0,即为不合法。
照这个过程,用线段树来模拟一下就行了,发现每次 cnt-- 的时候,意为 ) 抵消掉了 ( ,那么线段树 pushup 的时候,左端区间的 ( 可以和右边区间的 ) 抵消,左端区间的 ) 和右端区间的 ( 都不能被抵消,那么直接加上即可,最后根节点的 ( ) 两个的数量都为 0 的时候即合法。

花里胡哨的做法。。

#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<map>
#include<cmath>
#include<cctype>
#include<vector>
#include<set>
#include<queue>
#include<algorithm>
#include<sstream>
#define X first
#define Y second
#define L (u<<1)
#define R (u<<1|1)
#define Mid (tr[u].l+tr[u].r>>1)
#define Len(u) (tr[u].r-tr[u].l+1)
using namespace std;

typedef long long LL;
typedef pair<int,int> PII;

const int N=100010,mod=1e9+7,INF=0x3f3f3f3f;
const double eps=1e-6;

int n,m;
string s;
struct Node
{
    int l,r;
    int a,b;
}tr[N<<2];

void pushup(int u)
{
    if(tr[L].a>=tr[R].b) tr[u].a=tr[L].a-tr[R].b,tr[u].b=0;
    else tr[u].a=0,tr[u].b=tr[R].b-tr[L].a;
    tr[u].a+=tr[R].a,tr[u].b+=tr[L].b;
}

void build(int u,int l,int r)
{
    tr[u]={l,r};
    if(l==r)
    {
        tr[u].a=(s[l-1]=='(');
        tr[u].b=(s[l-1]==')');
      
        return;
    }
    build(L,l,Mid),build(R,Mid+1,r);
    pushup(u);
}

void modify(int u,int l,int r)
{
    if(tr[u].l==l&&tr[u].r==r)
    {
        tr[u].a^=1,tr[u].b^=1;
        return;
    }
    if(l<=Mid) modify(L,l,r);
    if(r>Mid) modify(R,l,r);
    pushup(u);
}

int main()
{
//	ios::sync_with_stdio(false);
//	cin.tie(0);

    cin>>n>>m>>s;
    build(1,1,n);
    while(m--)
    {
        int x;
        scanf("%d",&x);
        modify(1,x,x);
        if(tr[1].a!=0||tr[1].b!=0) puts("No");
        else puts("Yes");
    }


	return 0;
}
/*

*/









猜你喜欢

转载自blog.csdn.net/DaNIelLAk/article/details/106530727