[模板] 三维偏序 - 树套树,线段树

Posted mollnn

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[模板] 三维偏序 - 树套树,线段树相关的知识,希望对你有一定的参考价值。

#include <bits/stdc++.h>
using namespace std;

const int N = 2e+7 + 5;

struct Pt {
    int a, b, c;
    int id;
    bool operator<(const Pt &x) const { return a < x.a; }
} p[N];

map<int, int> ma, mb, mc;
int aa[N], ab[N], ac[N];
int ida, idb, idc;
int n;
int ans[N];

namespace segc {
int val[N], ch[N][2], root[N], ind;
void pushup(int p) { val[p] = val[ch[p][0]] + val[ch[p][1]]; }
void modify(int p, int l, int r, int pos) {
    if (l == r) {
        val[p]++;
    } else {
        if (pos <= (l + r) / 2) {
            if (!ch[p][0])
                ch[p][0] = ++ind;
            modify(ch[p][0], l, (l + r) / 2, pos);
        } else {
            if (!ch[p][1])
                ch[p][1] = ++ind;
            modify(ch[p][1], (l + r) / 2 + 1, r, pos);
        }
        pushup(p);
    }
}
void modify(int ver, int pos) {
    if (!root[ver])
        root[ver] = ++ind;
    modify(root[ver], 1, n, pos);
}
int query(int p, int l, int r, int ql, int qr) {
    if (l > qr || r < ql || p == 0)
        return 0;
    if (l >= ql && r <= qr)
        return val[p];
    return query(ch[p][0], l, (l + r) / 2, ql, qr) + query(ch[p][1], (l + r) / 2 + 1, r, ql, qr);
}
int query(int ver, int ql, int qr) { return query(root[ver], 1, n, ql, qr); }
}  // namespace segc

namespace segb {
void modify(int p, int l, int r, int pos, int posi) {
    segc::modify(p, posi);
    if (l != r) {
        if (pos <= (l + r) / 2)
            segb::modify(p * 2, l, (l + r) / 2, pos, posi);
        else
            segb::modify(p * 2 + 1, (l + r) / 2 + 1, r, pos, posi);
    }
}
void modify(int pos, int posi) { modify(1, 1, n, pos, posi); }
int query(int p, int l, int r, int ql, int qr, int iql, int iqr) {
    if (l > qr || r < ql)
        return 0;
    if (l >= ql && r <= qr)
        return segc::query(p, iql, iqr);
    return query(p * 2, l, (l + r) / 2, ql, qr, iql, iqr) +
           query(p * 2 + 1, (l + r) / 2 + 1, r, ql, qr, iql, iqr);
}
int query(int ql, int qr, int iql, int iqr) { return query(1, 1, n, ql, qr, iql, iqr); }
}  // namespace segb

int k;

signed main() {
    scanf("%d%d", &n, &k);
    for (int i = 1; i <= n; i++) {
        scanf("%d%d%d", &p[i].a, &p[i].b, &p[i].c);
        ma[p[i].a]++;
        mb[p[i].b]++;
        mc[p[i].c]++;
        p[i].id = i;
    }
    for (map<int, int>::iterator it = ma.begin(); it != ma.end(); it++)
        it->second = ++ida, aa[ida] = it->first;
    for (map<int, int>::iterator it = mb.begin(); it != mb.end(); it++)
        it->second = ++idb, ab[idb] = it->first;
    for (map<int, int>::iterator it = mc.begin(); it != mc.end(); it++)
        it->second = ++idc, ac[idc] = it->first;
    for (int i = 1; i <= n; i++) {
        p[i].a = ma[p[i].a];
        p[i].b = mb[p[i].b];
        p[i].c = mc[p[i].c];
    }

    sort(p + 1, p + n + 1);
    for (int i = 1; i <= n;) {
        int j;
        for (j = i; j <= n; j++)
            if (p[i].a != p[j].a)
                break;
        --j;
        for (int k = i; k <= j; k++) segb::modify(p[k].b, p[k].c);
        for (int k = i; k <= j; k++) {
            ans[segb::query(1, p[k].b, 1, p[k].c)]++;
        }
        i = j + 1;
    }
    for (int i = 1; i <= n; i++) printf("%d
", ans[i]);
}

以上是关于[模板] 三维偏序 - 树套树,线段树的主要内容,如果未能解决你的问题,请参考以下文章

「luogu3380」模板二逼平衡树(树套树)

bzoj2141排队 [国家集训队2011]排队(魏铭) 树套树 线段树套替罪羊树

树套树初探

洛谷 P3380 模板二逼平衡树(树套树)

洛谷P3380 模板二逼平衡树(树套树,树状数组,线段树)

[模板]洛谷T3380 二逼平衡树 线段树套Splay