Problem Description

Jam like to solve the problem which on the 3D-axis,given N(1≤N≤100000) points (x,y,z)(1≤x,y,z≤100000)

If two point such as (xi,yi,zi) and (xj,yj,zj) xi≥xj yi≥yj zi≥zj, the bigger one level add 1

Ask for the each level of the point.

Input
The first line is T(1≤T≤15) means T Case

For each case

The first line is N means the number of Point and next there are N line, each line has (x,y,z)

Output
Output with N line,each line has one number means the lever of point

Sample Input
1
4
10 4 7
10 6 6
8 2 5
7 3 10

Sample Output
1
1
0
0


明显不过的三维偏序问题,cdq分治即可。

我们对x排序之后,cdq分治y,在树状数组上查找z。


AC代码:

#pragma GCC optimize(2)
#include<bits/stdc++.h>
//#define int long long
#define lowbit(x) (x&(-x))
using namespace std;
const int N=1e5+10;
int T,n,res[N],m=1e5,d[N];
struct node{int x,y,z,id,res;}t[N];
bool operator == (node a,node b){return a.x==b.x&&a.y==b.y&&a.z==b.z;}
int cmpx(node a,node b){return (a.y==b.y&&a.x==b.x)?(a.z<b.z):(a.x==b.x?a.y<b.y:a.x<b.x);}
int cmpy(node a,node b){return a.y==b.y?a.z<b.z:a.y<b.y;}
inline void add(int x,int v){for(;x<=m;x+=lowbit(x)) d[x]+=v;}
inline int ask(int x){int res=0; for(;x;x-=lowbit(x)) res+=d[x]; return res;}
void cdq(int l,int r){
	if(l==r)	return ;	int mid=l+r>>1;
	cdq(l,mid);	cdq(mid+1,r);	int j=l;
	for(int i=mid+1;i<=r;i++){
		while(j<=mid&&t[j].y<=t[i].y) add(t[j++].z,1);
		t[i].res+=ask(t[i].z);
	}
	for(int i=l;i<j;i++)	add(t[i].z,-1);
	sort(t+l,t+r+1,cmpy);
}
signed main(){
	cin>>T;
	while(T--){
		scanf("%d",&n); memset(t,0,sizeof t); memset(d,0,sizeof d);
		for(int i=1;i<=n;i++)	scanf("%d %d %d",&t[i].x,&t[i].y,&t[i].z),t[i].id=i;
		sort(t+1,t+1+n,cmpx);	cdq(1,n);
		for(int i=n-1;i>=1;i--)	if(t[i]==t[i+1])	t[i].res=t[i+1].res;
		for(int i=1;i<=n;i++)	res[t[i].id]=t[i].res;
		for(int i=1;i<=n;i++)	printf("%d\n",res[i]);
	}
	return 0;
}