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;
}
posted @ 2022-03-01 15:38  Nepenthe8  阅读(54)  评论(0编辑  收藏  举报