• AtCoder Beginner Contest 223 F Parenthesis Checking(线段树)


    Parenthesis Checking

    题目大意:

    给出一个括号串,q 次以下两种操作:

    1. 输入 1 l r,交换第 \(l\)-th 和 \(r\)-th 的字符
    2. 输出 2 l r ,查询区间 \([l, r]\) 子串是否是合法括号序列。
    思路:

    (\(1\))\(-1\)

    一个括号序列是否合法,关键在于判断序列是否前缀和为 0 且前缀和最小值为 0。

    考虑使用线段树来维护区间和与前缀和最小值的信息。

    struct Node {
        int sum;
        int minn; // 前缀和的最小值
        Node(int x = 0) : sum(x), minn(x) {}
        Node operator+(const Node &node) const {
            Node res;
            res.minn = min(minn, sum + node.minn);
            res.sum = sum + node.sum;
            return res;
        }
        bool operator()() const {
            return sum == 0 && minn == 0;
        }
    };
    

    区间和不必多说。

    考虑前缀和的最小值,要么是左子节点前缀和的最小值,要么是左节点的区间和 + 右子节点前缀和的最小值,两者取 min。

    Code:
    #define ls (v << 1)
    #define rs (ls | 1)
    #define tm ((tl + tr) >> 1)
    struct Segment {
        int n;
        vector<Node> nodes;
        Segment(string &s) : n((int)s.length()), nodes(n << 2) {
            function<void(int, int, int)> dfs = [&](int v, int tl, int tr) { // 节点标号,维护的区间
                if (tl == tr) {
                    nodes[v] = Node(s[tm - 1] == '(' ? 1 : -1);
                } else {
                    dfs(ls, tl, tm);
                    dfs(rs, tm + 1, tr);
                    nodes[v] = nodes[ls] + nodes[rs];
                }
            };
            dfs(1, 1, n);
        }
        void upd(int x, int y) {
            function<void(int, int, int)> dfs = [&](int v, int tl, int tr) {
                if (tl == tr) {
                    nodes[v] = Node(y);
                } else {
                    if (x <= tm) 
                        dfs(ls, tl, tm);
                    else
                        dfs(rs, tm + 1, tr);
                    nodes[v] = nodes[ls] + nodes[rs];
                }
            };
            dfs(1, 1, n);
        }
        bool query(int x, int y) {
            function<Node(int, int, int)> dfs = [&](int v, int tl, int tr) {
                if (x <= tl && tr <= y)
                    return nodes[v];
                if (y <= tm)
                    return dfs(ls, tl, tm);
                if (x > tm)
                    return dfs(rs, tm + 1, tr);
                return dfs(ls, tl, tm) + dfs(rs, tm + 1, tr);
            };
            return dfs(1, 1, n)();
        }
    };
     
    int main() {
        ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
        int n, q;
        cin >> n >> q;
        string s;
        cin >> s;
        Segment seg(s);
        while (q--) {
            int op, l, r;
            cin >> op >> l >> r;
            if (op == 1) {
                if (s[l - 1] != s[r - 1]) {
                    int tmp = s[r - 1] == '(' ? 1 : -1;
                    seg.upd(l, tmp);
                    seg.upd(r, -tmp);
                    swap(s[l - 1], s[r - 1]);
                }
            } else {
                cout << (seg.query(l, r) ? "Yes" : "No") << "\n";
            }
        }
        return 0;
    }
    
  • 相关阅读:
    background和background-size
    获取表单的初始值,模拟placeholder属性
    input[type=checkbox]
    background-size
    input的type属性的修改
    选项卡切换
    2016.12.13
    3. 如何封装查询条件与查询结果到map中
    Java 实现网站当前在线用户统计
    sell-- wordPOI
  • 原文地址:https://www.cnblogs.com/Nepenthe8/p/15950543.html
Copyright © 2020-2023  润新知