UESTC 1546 Bracket Sequence

UESTC_1546

    这个题目可以借用判断合法括号序列的办法,将’(’看作1,将’)’看作-1,之后从左向右扫描一个序列并将扫描到的值累加起来,在这个过程中如果任意时刻这些值的和都不小于0,并且最后的时候这些值的和为0,那么就说明这个括号序列是合法的。

    于是我们只要再用线段树实现修改及查询的操作,这个题目就算是解决了。为了便于修改和查询,我们可以用两个标记to、rev,to表示这个区间是否被set,rev表示这个区间是否被翻转。同时我们可以维护3个值lmin、lmax、sum,lmin表示从当前区间左端点开始最小的前缀和,lmax表示从当前区间开始最大的前缀和,sum表示当前区间的和。

#include<stdio.h>

#include<string.h>

#define MAXD 100010

int N, M, to[4 * MAXD], rev[4 * MAXD], lmin[4 * MAXD], lmax[4 * MAXD], sum[4 * MAXD];

char b[MAXD];

void Swap(int &x, int &y)

{

    int t;

    t = x, x = -y, y = -t;

}

void pushdown(int cur, int x, int y)

{

    int mid = (x + y) >> 1, ls = cur << 1, rs = cur << 1 | 1;

    if(to[cur] != -1)

    {

        to[ls] = to[rs] = to[cur];

        rev[ls] = rev[rs] = 0;

        if(to[cur])

        {

            sum[ls] = mid - x + 1, sum[rs] = y - mid;

            lmin[ls] = lmin[rs] = 0;

            lmax[ls] = mid - x + 1, lmax[rs] = y - mid;

        }

        else

        {

            sum[ls] = -(mid - x + 1), sum[rs] = -(y - mid);

            lmin[ls] = -(mid - x + 1), lmin[rs] = -(y - mid);

            lmax[ls] = lmax[rs] = 0;

        }

        to[cur] = -1;

    }

    if(rev[cur])

    {

        rev[ls] ^= 1, rev[rs] ^= 1;

        sum[ls] = -sum[ls], sum[rs] = -sum[rs];

        Swap(lmin[ls], lmax[ls]), Swap(lmin[rs], lmax[rs]);

        rev[cur] = 0;

    }

}

void update(int cur)

{

    int ls = cur << 1, rs = cur << 1 | 1;

    sum[cur] = sum[ls] + sum[rs];

    lmin[cur] = lmin[ls];

    if(sum[ls] + lmin[rs] < lmin[cur])

        lmin[cur] = sum[ls] + lmin[rs];

    lmax[cur] = lmax[ls];

    if(sum[ls] + lmax[rs] > lmax[cur])

        lmax[cur] = sum[ls] + lmax[rs];

}

void build(int cur, int x, int y)

{

    int mid = (x + y) >> 1, ls = cur << 1, rs = cur << 1 | 1;

    to[cur] = -1, rev[cur] = 0;

    if(x == y)

    {

        if(b[x] == '(')

            sum[cur] = lmax[cur] = 1, lmin[cur] = 0;

        else

            sum[cur] = lmin[cur] = -1, lmax[cur] = 0;

        return ;

    }

    build(ls, x, mid);

    build(rs, mid + 1, y);

    update(cur);

}

void query(int cur, int x, int y, int s, int t, int &min, int &ss)

{

    int mid = (x + y) >> 1, ls = cur << 1, rs = cur << 1 | 1;

    if(x >= s && y <= t)

    {

        if(ss + lmin[cur] < min)

            min = ss + lmin[cur];

        ss += sum[cur];

        return ;

    }

    pushdown(cur, x, y);

    if(mid >= s)

        query(ls, x, mid, s, t, min, ss);

    if(mid + 1 <= t)

        query(rs, mid + 1, y, s, t, min, ss);

}

void refresh(int cur, int x, int y, int s, int t, int c)

{

    int mid = (x + y) >> 1, ls = cur << 1, rs = cur << 1 | 1;

    if(x >= s && y <= t)

    {

        to[cur] = c, rev[cur] = 0;

        if(c)

            sum[cur] = lmax[cur] = y - x + 1, lmin[cur] = 0;

        else

            sum[cur] = lmin[cur] = -(y - x + 1), lmax[cur] = 0;

        return ;

    }

    pushdown(cur, x, y);

    if(mid >= s)

        refresh(ls, x, mid, s, t, c);

    if(mid + 1 <= t)

        refresh(rs, mid + 1, y, s, t, c);

    update(cur);

}

void Reverse(int cur, int x, int y, int s, int t)

{

    int mid = (x + y) >> 1, ls = cur << 1, rs = cur << 1 | 1;

    if(x >= s && y <= t)

    {

        rev[cur] ^= 1;

        sum[cur] = -sum[cur], Swap(lmin[cur], lmax[cur]);

        return ;

    }

    pushdown(cur, x, y);

    if(mid >= s)

        Reverse(ls, x, mid, s, t);

    if(mid + 1 <= t)

        Reverse(rs, mid + 1, y, s, t);

    update(cur);

}

void solve()

{

    int i, q, x, y, min, ss;

    char ch[10];

    scanf("%d", &q);

    for(i = 0; i < q; i ++)

    {

        scanf("%s%d%d", ch, &x, &y);

        if(ch[0] == 's')

        {

            scanf("%s", ch);

            refresh(1, 0, N - 1, x, y, ch[0] == '(' ? 1 : 0);

        }

        else if(ch[0] == 'r')

            Reverse(1, 0, N - 1, x, y);

        else

        {

            min = ss = 0;

            query(1, 0, N - 1, x, y, min, ss);

            if(ss == 0 && min == 0)

                printf("YES\n");

            else

                printf("NO\n");

        }

    }

}

void init()

{

    scanf("%d", &N);

    scanf("%s", b);

    build(1, 0, N - 1);

}

int main()

{

    int t, tt;

    scanf("%d", &t);

    for(tt = 0; tt < t; tt ++)

    {

        init();

        printf("Case %d:\n", tt + 1);

        solve();

        printf("\n");

    }

    return 0;

}

你可能感兴趣的:(sequence)