【题目链接】
【思路要点】
- 直观地来想,本题可以先排序一维,然后使用二维数据结构(树套树,KD-Tree)来解决。
- 时间复杂度\(O(NLog^{2}N)\)或\(O(N\sqrt{N})\)。
- 或者也可以用CDQ分治来解决本题,时间复杂度同样为\(O(NLog^{2}N)\)。
- 其中树套树的空间复杂度高达\(O(NLog^{2}N)\),粗糙的实现可能导致MLE。
- 笔者使用的是CDQ分治的做法。
【代码】
#include<bits/stdc++.h> using namespace std; #define MAXN 200005 struct info {int x, y, z, ans; }; bool cmp(info x, info y) {return x.x < y.x; } int n, m, BIT[MAXN]; info a[MAXN], b[MAXN]; void work(int l, int r) { if (l == r) {a[l].ans++; return; } int mid = (l + r) / 2; work(l, mid); work(mid + 1, r); int point = l; for (int i = mid + 1; i <= r; i++) { while (point <= mid && a[i].y >= a[point].y) { for (int j = a[point].z; j <= m; j += j & -j) BIT[j]++; point++; } for (int j = a[i].z; j >= 1; j -= j & -j) a[i].ans += BIT[j]; } for (int i = l; i < point; i++) for (int j = a[i].z; j <= m; j += j & -j) BIT[j]--; int minnum = m; for (int i = mid + 1; i <= r; i++) minnum = min(minnum, a[i].x); point = mid + 1; for (int i = l; i <= mid; i++) { if (a[i].x < minnum) continue; while (point <= r && a[i].y >= a[point].y) { if (a[point].x == minnum) for (int j = a[point].z; j <= m; j += j & -j) BIT[j]++; point++; } for (int j = a[i].z; j >= 1; j -= j & -j) a[i].ans += BIT[j]; } for (int i = mid+1; i < point; i++) if (a[i].x == minnum) for (int j = a[i].z; j <= m; j += j & -j) BIT[j]--; int pointI = l, pointII = mid + 1; for (int i = l; i <= r; i++) if (pointII > r || pointI <= mid && a[pointI].y < a[pointII].y) b[i] = a[pointI++]; else b[i] = a[pointII++]; for (int i = l; i <= r; i++) a[i] = b[i]; } int main() { scanf("%d%d", &n, &m); for (int i = 1; i <= n; i++) scanf("%d%d%d", &a[i].x, &a[i].y, &a[i].z); sort(a + 1, a + 1 + n, cmp); work(1, n); static int ans[MAXN]; for (int i = 1; i <= n; i++) ans[a[i].ans]++; for (int i = 1; i <= n; i++) printf("%d\n", ans[i]); return 0; }