题意:三维偏序,每个点求出三个坐标都小于等于他的点的个数。
第三维排序后cdq分治,统计前一半对后一半的影响的时候按照第一位排序第二维树状数组维护。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <cmath>
#include <map>
using namespace std;
#define maxn 100005
struct node {
int id;
int x, y, z;
bool operator == (const node &a) const {
return x == a.x && y == a.y && z == a.z;
}
}qu[maxn], tmp[maxn];
int ans[maxn];
int c[maxn];
int n, Max;
bool cmp1 (const node &a, const node &b) {
if (a.z != b.z)
return a.z < b.z;
return a.x < b.x || (a.x == b.x && a.y < b.y);
}
bool cmp2 (const node &a, const node &b) {
return a.x < b.x || (a.x == b.x && a.y < b.y);
}
int lowbit (int x) {
return x&(-x);
}
void add (int x) {
for (int i = x; i < maxn; i += lowbit (i))
c[i]++;
}
int sum (int x) {
int ans = 0;
for (int i = x; i > 0; i -= lowbit (i))
ans += c[i];
return ans;
}
void clear (int x) {
for (int i = x; i < maxn; i += lowbit (i))
c[i] = 0;
}
void solve (int l, int r) {
if (l == r)
return ;
int mid = (l+r)>>1;
solve (l, mid);
for (int i = l; i <= r; i++) tmp[i] = qu[i];
sort (tmp+l, tmp+mid+1, cmp2);
sort (tmp+mid+1, tmp+r+1, cmp2);
int L = l;
for (int i = mid+1; i <= r; i++) {
while (L <= mid && tmp[L].x <= tmp[i].x) {
add (tmp[L].y);
L++;
}
ans[tmp[i].id] += sum (tmp[i].y);
}
for (int i = l; i <= mid; i++) {
clear (tmp[i].y);
}
solve (mid+1, r);
}
int main () {
int t;
scanf ("%d", &t);
while (t--) {
scanf ("%d", &n);
memset (c, 0, sizeof c);
memset (ans, 0, sizeof ans);
for (int i = 1; i <= n; i++) {
scanf ("%d%d%d", &qu[i].x, &qu[i].y, &qu[i].z);
qu[i].id = i;
}
sort (qu+1, qu+1+n, cmp1);
solve (1, n);
for (int i = n-1; i >= 1; i--) {
if (qu[i] == qu[i+1])
ans[qu[i].id] = ans[qu[i+1].id];
}
for (int i = 1; i <= n; i++) {
printf ("%d\n", ans[i]);
}
}
return 0;
}