zoukankan      html  css  js  c++  java
  • uestc 94(区间更新)

    题意:有一个字符串全部由’(‘和’)’组成。然后有三种操作,query a b输出区间[a,b]字符串的括号序列是否合法。reverse a b把区间[a,b]字符串里全部’(‘替换成’)’,而且把全部’)’替换为’(‘,set a b c,把区间[a,b]的全部字符替换为c。
    题解:明显是线段树,为了能够让线段树维护,推断一个字符串是否为合法括号,能够把全部的’(‘替换为-1,’)’替换为1,那么假设这个字符串合法,整个字符串的和应该是0且前缀最大和不能超过0。所以能够在线段树节点加入maxx和sum这两个值维护区间内的前缀最大和和总和。

    然后reverse操作时。为了方便计算maxx,节点应该还要维护minn前缀最小和,这样maxx = -minn能够直接计算。还有区间合并时最大和是选左子区间最大和与左子区间总和加上右子区间的最大和中较大的那个。最小和求法同理。

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    const int N = 100005;
    struct Tree {
        int sum, maxx, minn;
        int setv, rev;
        void f(int val, int left, int right) {
            if (!val) {
                sum = -sum;
                int temp = maxx;
                maxx = -minn;
                minn = -temp;
                rev ^= 1;
            }
            else {
                minn = min(val, val * (right - left + 1));  
                maxx = max(val, val * (right - left + 1));
                sum = val * (right - left + 1);
                setv = val;
                rev = 0;
            }
        }
    }tree[N << 2];
    int n, q, a[N];
    char s[N], op[10], c[5];
    
    void pushdown(int k, int left, int right) {
        int mid = (left + right) / 2;
        if (tree[k].setv) {
            tree[k * 2].f(tree[k].setv, left, mid);
            tree[k * 2 + 1].f(tree[k].setv, mid + 1, right);
            tree[k].setv = 0;
        }
        if (tree[k].rev) {
            tree[k * 2].f(0, left, mid);
            tree[k * 2 + 1].f(0, mid + 1, right);
            tree[k].rev = 0;
        }
    }
    
    void pushup(int k) {
        tree[k].sum = tree[k * 2].sum + tree[k * 2 + 1].sum;
        tree[k].maxx = max(tree[k * 2].maxx, tree[k * 2].sum + tree[k * 2 + 1].maxx);
        tree[k].minn = min(tree[k * 2].minn, tree[k * 2].sum + tree[k * 2 + 1].minn);
    }
    
    void build(int k, int left, int right) {
        tree[k].setv = tree[k].rev = 0;
        if (left == right) {
            tree[k].sum = tree[k].maxx = tree[k].minn = a[left];
            return;
        }
        int mid = (left + right) / 2;
        build(k * 2, left, mid);
        build(k * 2 + 1, mid + 1, right);
        pushup(k);
    }
    
    void modify(int k, int left, int right, int l, int r, int v) {
        if (l <= left && right <= r) {
            tree[k].f(v, left, right);
            return;
        }
        pushdown(k, left, right);
        int mid = (left + right) / 2;
        if (l <= mid)
            modify(k * 2, left, mid, l, r, v);
        if (r > mid)
            modify(k * 2 + 1, mid + 1, right, l, r, v);
        pushup(k);
    }
    
    void query(int k, int left, int right, int l, int r, int &sum, int &maxx) {
        if (l <= left && right <= r) {
            maxx = tree[k].maxx;
            sum = tree[k].sum;
            return;
        }
        pushdown(k, left, right);
        int mid = (left + right) / 2;
        if (r <= mid)
            query(k * 2, left, mid, l, r, sum, maxx);
        else if (l > mid)
            query(k * 2 + 1, mid + 1, right, l, r, sum, maxx);
        else {
            int sum1, maxx1, sum2, maxx2;
            query(k * 2, left, mid, l, mid, sum1, maxx1);
            query(k * 2 + 1, mid + 1, right, mid + 1, r, sum2, maxx2);
            sum = sum1 + sum2;
            maxx = max(maxx1, sum1 + maxx2);
        }
        pushup(k);
    }
    
    int main() {
        int t, cas = 1;
        scanf("%d", &t);
        while (t--) {
            scanf("%d%s", &n, s + 1);
            for (int i = 1; i <= n; i++)
                if (s[i] == '(')
                    a[i] = -1;
                else
                    a[i] = 1;
            build(1, 1, n);
            printf("Case %d:
    ", cas++);
            scanf("%d", &q);
            int l, r, sum, maxx;
            while (q--) {
                scanf("%s", op);
                if (op[0] == 'q') {
                    scanf("%d%d", &l, &r);
                    query(1, 1, n, l + 1, r + 1, sum, maxx);
                    if (!sum && maxx <= 0)
                        printf("YES
    ");
                    else
                        printf("NO
    ");
                }
                else if (op[0] == 's') {
                    scanf("%d%d%s", &l, &r, c);
                    if (c[0] == '(')
                        modify(1, 1, n, l + 1, r + 1, -1);
                    else
                        modify(1, 1, n, l + 1, r + 1, 1);
                }
                else {
                    scanf("%d%d", &l, &r);
                    modify(1, 1, n, l + 1, r + 1, 0);
                }
            }
            printf("
    ");
        }
        return 0;
    }
  • 相关阅读:
    004-核心技术-netty概述、传统IO、Reactor线程模型
    003-核心技术-IO模型-NIO-基于NIO群聊示例
    002-核心技术-IO模型-NIO【Selector、Channel、Buffer】、零拷贝
    018-redis-命令合计
    【整理】js、python、java分别对url进行编码和解码
    深度 | 翟东升:写在美帝国撤军和阿富汗政权溃散之际
    修改Windows10 命令终端cmd的编码为UTF-8 && IDEA控制台输出中文乱码
    Dockerfile文件中的ENTRYPOINT,CMD命令跟k8s中command,args之间的关系
    服务器带宽,流量之间的关系
    值得收藏的下载地址
  • 原文地址:https://www.cnblogs.com/claireyuancy/p/6979469.html
Copyright © 2011-2022 走看看