From d0bcccde01955b63c0a95d180163aaae493ec4ce Mon Sep 17 00:00:00 2001 From: hanyixuanten <105723997+hanyixuanten@users.noreply.github.com> Date: Tue, 22 Sep 2026 13:20:22 +0000 Subject: [PATCH] new file: P3810.cpp --- P3810.cpp | 91 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100755 P3810.cpp diff --git a/P3810.cpp b/P3810.cpp new file mode 100755 index 0000000..1cbd083 --- /dev/null +++ b/P3810.cpp @@ -0,0 +1,91 @@ +#include +using namespace std; +const int maxn = 100005; +struct Node { + int a, b, c; + int cnt = 1; // 相同三元组的个数 + int id = 0; // 在去重数组中的编号 + bool operator<(const Node &o) const { + if (a != o.a) + return a < o.a; + if (b != o.b) + return b < o.b; + return c < o.c; + } +} e[maxn], tmp[maxn]; +int n, k, m; +int ans[maxn]; // ans[i]: 去重后第 i 个元素的答案 +int res[maxn]; // res[d]: 答案恰为 d 的元素个数 +struct BIT { + int tree[200005]; + int lowbit(int x) { return x & -x; } + void add(int x, int v) { + for (; x <= k; x += lowbit(x)) + tree[x] += v; + } + int sum(int x) { + int r = 0; + for (; x > 0; x -= lowbit(x)) + r += tree[x]; + return r; + } +} bit; +void cdq(int l, int r) { + if (l == r) + return; + int mid = (l + r) >> 1; + cdq(l, mid); + cdq(mid + 1, r); + // 左半 -> 右半 的贡献:b 用双指针,c 用树状数组 + int i = l, j = mid + 1; + while (j <= r) { + while (i <= mid && e[i].b <= e[j].b) { + bit.add(e[i].c, e[i].cnt); + ++i; + } + ans[e[j].id] += bit.sum(e[j].c); + ++j; + } + // 撤销树状数组(不能 memset,太慢,要按插入的反操作回滚) + for (int t = l; t < i; ++t) + bit.add(e[t].c, -e[t].cnt); + // 归并:让 e[l..r] 按 b 有序,供上一层双指针使用 + i = l; + j = mid + 1; + int t = l; + while (i <= mid && j <= r) + tmp[t++] = (e[i].b <= e[j].b) ? e[i++] : e[j++]; + while (i <= mid) + tmp[t++] = e[i++]; + while (j <= r) + tmp[t++] = e[j++]; + for (t = l; t <= r; ++t) + e[t] = tmp[t]; +} + +int main() { + scanf("%d%d", &n, &k); + for (int i = 1; i <= n; ++i) + scanf("%d%d%d", &e[i].a, &e[i].b, &e[i].c); + sort(e + 1, e + n + 1); + // 去重 + m = 0; + for (int i = 1; i <= n; ++i) { + if (i > 1 && e[i].a == e[m].a && e[i].b == e[m].b && e[i].c == e[m].c) { + ++e[m].cnt; + } else { + e[++m] = e[i]; + e[m].cnt = 1; + } + } + for (int i = 1; i <= m; ++i) + e[i].id = i; + cdq(1, m); + for (int i = 1; i <= m; ++i) { + ans[e[i].id] += e[i].cnt - 1; // 与自己完全相同的同族元素 + res[ans[e[i].id]] += e[i].cnt; + } + for (int d = 0; d < n; ++d) + printf("%d\n", res[d]); + return 0; +} \ No newline at end of file