【CDQ分治】【模板】三维偏序(陌上花开)

P3810 【模板】三维偏序(陌上花开) - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

#include <bits/stdc++.h>

using namespace std;

using i64 = long long;

template<typename T>
struct BIT {
#ifndef lowbit
#define lowbit(x) (x & (-x));
#endif
    int n;
    vector<T> t;

    BIT () {}
    BIT (int _n): n(_n) { t.resize(_n + 1); }
    BIT (int _n, vector<T>& a): n(_n) {
        t.resize(_n + 1);
        for (int i = 1; i <= n; ++ i) {
            t[i] += a[i];
            int j = i + lowbit(i);
            if (j <= n) t[j] += t[i];
        }
    }
    //单点修改
    void update(int i, T x) {
        while (i <= n) {
            t[i] += x;
            i += lowbit(i);
        }
    }
    //区间查询
    T sum(int i) {
        T ans = 0;
        while (i > 0) {
            ans += t[i];
            i -= lowbit(i);
        }
        return ans;
    }

    T query(int i, int j) {
        return sum(j) - sum(i - 1);
    }
    //区间修改则存入差分数组,[l, r] + k则update(x,k),update(y+1,-k)
    //单点查询则直接求前缀和sum(x)

    //求逆序对
    /*
    iota(d.begin(), d.end(), 0);
    stable_sort(d.begin(), d.end(), [&](int x, int y) {
        return a[x] < a[y];
    });去重排序

    BIT<i64> tree(n);
    i64 ans = 0;
    for (int i = 1; i <= n; i ++) {
        tree.update(d[i], 1);
        ans += i - tree.sum(d[i]);
    }
    */
};

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int n, k;
    cin >> n >> k;

    vector<array<int, 3>> a(n);
    for (auto &[x, y, z] : a)
        cin >> x >> y >> z;

    sort(a.begin(), a.end());

    vector<array<int, 5>> A;
    for (int i = 0; i < n; i ++) {
        int j = i;
        while (j + 1 < n && a[j + 1] == a[j]) {
            j ++;
        }
        A.push_back({a[j][0], a[j][1], a[j][2], j - i + 1, 0});
        i = j;
    }

    BIT<i64> bit(k);
    auto cdq = [&](auto && self, int l, int r)->void{
        if (l == r)
            return ;
        int mid = l + r >> 1;
        self(self, l, mid);
        self(self, mid + 1, r);

        sort(A.begin() + l, A.begin() + mid + 1, [](auto x, auto y) {
            if (x[1] == y[1]) return x[2] < y[2];
            return x[1] < y[1];
        });

        sort(A.begin() + mid + 1, A.begin() + r + 1, [](auto x, auto y) {
            if (x[1] == y[1]) return x[2] < y[2];
            return x[1] < y[1];
        });

        int i = l, j = mid + 1;
        while (j <= r) {
            while (i <= mid && A[i][1] <= A[j][1]) {
                bit.update(A[i][2], A[i][3]);
                i ++;
            }
            A[j][4] += bit.sum(A[j][2]);
            j ++;
        }

        for (int k = l; k < i; k ++)
            bit.update(A[k][2], -A[k][3]);
    };

    cdq(cdq, 0, A.size() - 1);

    vector<i64> f(n + 1);
    for (auto &[a, b, c, cnt, d] : A) {
        f[d + cnt - 1] += cnt;
    }

    for (int i = 0; i < n; i ++)
        cout << f[i] << "\n";

    return 0;
}
posted @ 2024-08-06 20:20  Ke_scholar  阅读(1)  评论(0编辑  收藏  举报