传送门:HTTP://acm.hdu.edu.cn/showproblem.php PID = 5618
题意:给你n个点的坐标x,y,z求xi <= x && yi <= y && zi <= z的个数有重点
2
1 1 1
1 1 1
1
1
思路:cdq分治求三维偏序对l-mid区间添加mid + 1,r区间查找
码:
#include<bits/stdc++.h>
using namespace std;
const int maxn = 110000;
struct node
{
int x, y, z, id;
} p[maxn],t[maxn];
int ans[maxn];
bool cmpx(node &a,node &b)
{
if(a.x == b.x && a.y == b.y && a.z == b.z) return a.id < b.id;
else if(a.x == b.x && a.y == b.y) return a.z < b.z;
else if(a.x == b.x) return a.y < b.y;
else return a.x < b.x;
}
bool cmpy(node &a,node &b)
{
if( a.y == b.y && a.z == b.z) return a.id < b.id;
else if(a.y == b.y) return a.z < b.z;
else return a.y < b.y;
}
int c[maxn],maxz;
inline int lowbit(int x){return x & (-x);}
void add(int x, int val){while(x <= maxz) c[x] += val, x += lowbit(x);}
int sum(int x) {int ret = 0;while(x > 0) ret += c[x], x -= lowbit(x);return ret;}
void cdq(int l, int r)
{
if(l == r) return ;
int mid = (l + r) / 2;
cdq(l, mid),cdq(mid + 1, r);
for(int i = l; i <= r; i++) t[i] = p[i];
sort(t + l, t + mid + 1, cmpy),sort(t + mid + 1, t + r + 1, cmpy);
int a1=l,a2=mid+1;
for(int i=l;i<=r;i++)
{
if(a1 == mid+1) ans[t[a2].id]+=sum(t[a2].z),a2++;
else if(a2 == r + 1) add(t[a1].z,1),a1++;
else if(t[a1].y <= t[a2].y) add(t[a1].z,1),a1++;
else ans[t[a2].id]+=sum(t[a2].z),a2++;
}
for(int i=l;i<=mid;i++) add(t[i].z,-1);
}
int main()
{
int t;scanf("%d",&t);
for(int cas=1;cas<=t;cas++)
{
int n;scanf("%d",&n);
for(int i=1;i<=n;i++) ans[i]=0;
maxz=-1;
for(int i = 1; i <= n; i++)
scanf("%d%d%d", &p[i].x, &p[i].y, &p[i].z),p[i].id = i,maxz=max(maxz,p[i].z);
sort(p + 1, p + 1 + n, cmpx);
cdq(1, n);
p[n+1].x=-1;
for(int i = n; i >= 1; i--)
{
if(p[i].x == p[i + 1].x && p[i].y == p[i + 1].y && p[i].z == p[i + 1].z)
ans[p[i ].id] = ans[p[i + 1].id];
}
for(int i = 1; i <= n; i++) printf("%d\n", ans[i]);
}
return 0;
}