可持久化线段树
2024年8月18日大约 2 分钟
可持久化线段树
| 题目 | 难度 | |
|---|---|---|
| LQ240615T9 小蓝的逆序对问题 | ||
| LQ240629T8 升级电缆 | 
主席树
主席树全称是可持久化权值线段树,参见 知乎讨论。
LQ240615T9 小蓝的逆序对问题
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e5 + 10, K = 22;
int n, q;
int st[K * N], L[K * N], R[K * N], idx = 1;
void build(int u = 1, int s = 0, int e = n - 1) {
    if (s == e) {
        st[u] = 0;
        return;
    }
    L[u] = idx++;
    R[u] = idx++;
    int m = (s + e) >> 1;
    build(L[u], s, m);
    build(R[u], m + 1, e);
}
int add(int i, int u, int s = 0, int e = n - 1) {
    int uu = idx++;
    if (s == e) {
        st[uu] = st[u] + 1;
        return uu;
    }
    int m = (s + e) >> 1;
    if (i <= m) {
        L[uu] = add(i, L[u], s, m);
        R[uu] = R[u];
    } else {
        L[uu] = L[u];
        R[uu] = add(i, R[u], m + 1, e);
    }
    st[uu] = st[L[uu]] + st[R[uu]];
    return uu;
}
int count(int l, int r, int ul, int ur, int s = 0, int e = n - 1) {
    if (e < l || r < s) return 0;
    if (l <= s && e <= r) {
        return st[ur] - st[ul];
    }
    int m = (s + e) >> 1;
    return count(l, r, L[ul], L[ur], s, m)
           + count(l, r, R[ul], R[ur], m + 1, e);
}
vector<int> discretize(vector<int> &vec) {
    vector<int> sorted_vec(vec);
    std::sort(sorted_vec.begin(), sorted_vec.end());
    sorted_vec.erase(std::unique(sorted_vec.begin(), sorted_vec.end()), sorted_vec.end());
    vector<int> result;
    result.reserve(vec.size());
    for (auto &v: vec) {
        int discrete_value = std::lower_bound(sorted_vec.begin(), sorted_vec.end(), v) - sorted_vec.begin();
        result.push_back(discrete_value);
    }
    return result;
}
int main() {
    cin >> n >> q;
    vector<int> a(n);
    for (auto &v: a) {
        cin >> v;
    }
    a = discretize(a);
    vector<int> root(n + 1);
    root[0] = 1;
    idx = 2;
    build();
    ll inv = 0;
    for (int i = 0; i < n; ++i) {
        inv += count(a[i] + 1, n - 1, root[0], root[i]);
        root[i + 1] = add(a[i], root[i]);
    }
    while (q--) {
        int i, j;
        cin >> i >> j;
        i--, j--;
        ll ans = inv;
        ans += count(a[i] + 1, n - 1, root[i + 1], root[j])
               - count(0, a[i] - 1, root[i + 1], root[j]);
        ans += count(0, a[j] - 1, root[i + 1], root[j])
               - count(a[j] + 1, n - 1, root[i + 1], root[j]);
        if (a[i] < a[j]) {
            ans++;
        } else if (a[i] > a[j]) {
            ans--;
        }
        cout << ans << endl;
    }
    return 0;
}(全文完)