fhq-teap怎么维护 father
查看原帖
fhq-teap怎么维护 father
225100
LargeRice16pro楼主2025/7/1 01:20

为什么在 merge 中,连接两点时更新 fa 数组是错的?

具体而言,将下述代码 77 行、83 行注释去掉,去掉 push_up 中维护的 fa,是错的。

但是不是 fa 被修改意味着儿子被修改,所以在修改儿子的时候修改父亲不对呢?

#include <bits/stdc++.h>
#define ls(x) tr[x].ls
#define rs(x) tr[x].rs
using namespace std;
typedef pair<int, int> pii;
const int N = 2e5 + 10;
struct node {
    int ls, rs;
    int val;
    int sz, s;
    char ch;
    bool tag;
};
node tr[N];
int root, idx;
bool vis[N];
int mp[N], fa[N];
int make_node(char ch) {
    tr[++idx] = {0, 0, -rand(), 1, (1 << (ch - 'a')), ch, 0};
    return idx;
}
void push_up(int p) {
    if (!p)
        return;
    if (ls(p))
        fa[ls(p)] = p;
    if (rs(p))
        fa[rs(p)] = p;
    tr[p].sz = tr[ls(p)].sz + tr[rs(p)].sz + 1;
    tr[p].s = tr[ls(p)].s | tr[rs(p)].s | (1 << (tr[p].ch - 'a'));
}
void eval(node &t) { t.tag = t.tag ^ 1; }
void push_down(int p) {
    if (!p)
        return;
    if (tr[p].tag) {
        eval(tr[ls(p)]);
        eval(tr[rs(p)]);
        swap(ls(p), rs(p));
        tr[p].tag = 0;
    }
}
tuple<int, int, int> split_by_rank(int p, int rank) {
    if (!p)
        return {0, 0, 0};
    push_down(p);
    if (rank <= tr[ls(p)].sz) {
        int l, mid, r;
        tie(l, mid, r) = split_by_rank(ls(p), rank);
        ls(p) = r;
        push_up(p);
        return {l, mid, p};
    } else if (rank <= tr[ls(p)].sz + 1) {
        int l = ls(p), r = rs(p);
        ls(p) = rs(p) = 0;
        return {l, p, r};
    } else {
        int l, mid, r;
        tie(l, mid, r) = split_by_rank(rs(p), rank - tr[ls(p)].sz - 1);
        rs(p) = l;
        push_up(p);
        return {p, mid, r};
    }
}
int merge(int u, int v) {
    push_down(u), push_down(v);
    push_up(u), push_up(v);
    if (!u && !v)
        return 0;
    if (u && !v)
        return u;
    if (!u && v)
        return v;
    if (tr[u].val < tr[v].val) {
        int now = merge(rs(u), v);
        rs(u) = now;
        // fa[now] = u;
        push_up(u);
        return u;
    } else {
        int now = merge(u, ls(v));
        ls(v) = now;
        // fa[now] = v;
        push_up(v);
        return v;
    }
}
int build(int l, int r, string &s) {
    if (l > r)
        return 0;
    int mid = l + r >> 1;
    int now = make_node(s[mid]);
    mp[mid] = now;
    int res1 = build(l, mid - 1, s), res2 = build(mid + 1, r, s);
    ls(now) = res1, fa[res1] = now;
    rs(now) = res2, fa[res2] = now;
    push_up(now);
    return now;
}
void insert(int x, char ch) {
    int l, mid, r;
    tie(l, mid, r) = split_by_rank(root, x);
    int a, b, c;
    tie(a, b, c) = split_by_rank(mid, 1);
    c = make_node(ch);
    mid = merge(merge(a, b), c);
    root = merge(merge(l, mid), r);
}
void remove(int x) {
    int l, mid, r;
    tie(l, mid, r) = split_by_rank(root, x);
    vis[mid] = 1;
    mid = 0;
    root = merge(merge(l, mid), r);
}
void rev(int x, int y) {
    int l, r, mid;
    tie(l, mid, r) = split_by_rank(root, x - 1);
    int a, b, c;
    tie(a, b, c) = split_by_rank(r, y - x + 2);
    eval(tr[a]);
    r = merge(merge(a, b), c);
    root = merge(merge(l, mid), r);
}
char get_rank(int x) {
    int l, mid, r;
    tie(l, mid, r) = split_by_rank(root, x);
    char res = tr[mid].ch;
    root = merge(merge(l, mid), r);
    return res;
}
int calc_rank(int p) {
    stack<int> q;
    int now = p;
    while (now != root) {
        q.push(now);
        now = fa[now];
    }
    q.push(root);
    while (q.size()) {
        auto now = q.top();
        q.pop();
        push_down(now);
    }
    now = p;
    int sz = tr[ls(p)].sz + 1;
    while (now != root) {
        int cur = fa[now];
        if (rs(cur) == now) {
            sz += tr[ls(cur)].sz + 1;
        }
        now = cur;
    }
    return sz;
}
int get_num(int x, int y) {
    int l, r, mid;
    tie(l, mid, r) = split_by_rank(root, x - 1);
    int a, b, c;
    tie(a, b, c) = split_by_rank(r, y - x + 2);
    int cnt = 0;
    for (int i = 0; i < 26; i++) {
        if ((tr[a].s >> i) & 1)
            cnt++;
    }
    r = merge(merge(a, b), c);
    root = merge(merge(l, mid), r);
    return cnt;
}
void solve() {
    int n, m;
    cin >> n >> m;
    string s;
    cin >> s;
    s = " " + s;
    root = build(1, n, s);
    while (m--) {
        char op;
        cin >> op;
        if (op == 'I') {
            int x;
            char c;
            cin >> x >> c;
            insert(x, c);
        } else if (op == 'D') {
            int x;
            cin >> x;
            remove(x);
        } else if (op == 'R') {
            int x, y;
            cin >> x >> y;
            rev(x, y);
        } else if (op == 'P') {
            int x;
            cin >> x;
            if (vis[mp[x]])
                cout << "0\n";
            else {
                cout << calc_rank(mp[x]) << '\n';
            }
        } else if (op == 'T') {
            int x;
            cin >> x;
            cout << get_rank(x) << '\n';
        } else {
            int x, y;
            cin >> x >> y;
            cout << get_num(x, y) << '\n';
        }
    }
}
signed main() {
    srand(unsigned(time(0)));
    ios::sync_with_stdio(0);
    cin.tie(0);
    int t = 1;
    // cin >> t;
    while (t--) {
        solve();
    }
    return 0;
}
2025/7/1 01:20
加载中...