BZOJ 3262: 陌上花开
经典的三维偏序问题,CDQ分治一维,树状数组维护一维
注意完全相等的情况
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 2e5 + 10; struct node { int id; int si, ci, mi; int cnt; void input(int id) { this->id = id; scanf("%d %d %d", &si, &ci, &mi); this->cnt = 0; } bool operator < (const node &other) const { if (si != other.si) return si > other.si; if (ci != other.ci) return ci > other.ci; return mi > other.mi; } }arr[maxn], brr[maxn], tarr[maxn]; int n, k; int ans[maxn]; int tot[maxn]; namespace BIT { int a[maxn]; void Init() { memset(a, 0, sizeof a); } void update(int x, int val) { for (; x <= k; x += x & -x) a[x] += val; } int query(int x) { int res = 0; for (; x > 0; x -= x & -x) res += a[x]; return res; } int query(int l, int r) { return query(r) - query(l - 1); } } int cmp(node a, node b) { return a.ci < b.ci; } void CDQ(int l, int r) { if (l > r) return; if (l == r) { ans[arr[l].id] += arr[l].cnt - 1; return; } int mid = (l + r) >> 1; for (int i = l; i <= r; ++i) tarr[i] = arr[i]; sort(tarr + l, tarr + mid + 1, cmp); sort(tarr + mid + 1, tarr + r + 1, cmp); int L = mid + 1, R = mid + 1; for (int i = l; i <= mid; ++i) { while (R <= r && tarr[i].ci >= tarr[R].ci) { BIT::update(tarr[R].mi, tarr[R].cnt); ++R; } ans[tarr[i].id] += BIT::query(tarr[i].mi); } while (L < R) { BIT::update(tarr[L].mi, -tarr[L].cnt); ++L; } CDQ(l, mid); CDQ(mid + 1, r); } void RUN() { while (~scanf("%d %d", &n, &k)) { BIT::Init(); memset(ans, 0, sizeof ans); memset(tot, 0, sizeof tot); for (int i = 1; i <= n; ++i) brr[i].input(i); sort(brr + 1, brr + 1 + n); int cnt = 0; for (int i = 1; i <= n; ++i) { if (i != 1 && brr[i - 1].si == brr[i].si && brr[i - 1].ci == brr[i].ci && brr[i - 1].mi == brr[i].mi) arr[cnt].cnt++; else arr[++cnt] = brr[i], arr[cnt].id = cnt, arr[cnt].cnt = 1; } CDQ(1, cnt); for (int i = 1; i <= cnt; ++i) { tot[ans[i]] += arr[i].cnt; } for (int i = 0; i < n; ++i) printf("%d\n", tot[i]); } } int main() { #ifdef LOCAL_JUDGE freopen("Text.txt", "r", stdin); #endif // LOCAL_JUDGE RUN(); return 0; }