zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    Linux下安装MySQL数据库(压缩包方式安装)
    使用Gitblit 在windows 上部署你的Git Server
    windows下使用docker的常用命令
    CentOS7安装Docker与使用篇
    linux安装redis
    Linux系统目录
    shiro之授权
    shiro之身份认证
    redis
    迅为4412uboot烧坏了报错问题
  • 原文地址:https://www.cnblogs.com/staginner/p/2494100.html
Copyright © 2011-2022 走看看