比较容易的CDQ分治吧..
第一维分治,第二维归并排序,第三维树状数组
题目链接:
#include<algorithm>
#include<ctype.h>
#include<cstdio>
#define N 200050
using namespace std;
inline int read(){
int x=0,f=1;char c;
do c=getchar(),f=c=='-'?-1:f; while(!isdigit(c));
do x=(x<<3)+(x<<1)+c-'0',c=getchar(); while(isdigit(c));
return x*f;
}
int Timer,n,maxn,top;
int q[N],time[N],cnt[N];
inline void Add(int x,int v){
for(;x<=maxn;x=x+(x&-x)){
if(time[x]!=Timer){
time[x]=Timer;
q[x]=0;
}
q[x]=q[x]+v;
}
}
inline int Sum(int x){
int tmp=0;
for(;x;x=x-(x&-x))
if(time[x]==Timer)
tmp=tmp+q[x];
return tmp;
}
struct Data{
int x,y,z,num,ans;
}a[N],b[N];
inline bool cmp(Data a,Data b){
return a.x==b.x?(a.y==b.y?a.z<b.z:a.y<b.y):(a.x<b.x);
}
void CDQ(int l,int r){
if(l==r) return;
int mid=(l+r)>>1;
CDQ(l,mid);CDQ(mid+1,r);
Timer++;
int i=l,j=mid+1;
for(;j<=r;j++){
while(a[i].y<=a[j].y && i<=mid){
Add(a[i].z,a[i].num);
i++;
}
a[j].ans+=Sum(a[j].z);
}
i=l;j=mid+1;
int tot=l;
while(i<=mid && j<=r){
if(a[i].y<a[j].y) b[tot++]=a[i++];
else b[tot++]=a[j++];
}
while(i<=mid) b[tot++]=a[i++];
while(j<=r) b[tot++]=a[j++];
for(int i=l;i<=r;i++)
a[i]=b[i];
return;
}
int main(){
n=read();maxn=read();
for(int i=1;i<=n;i++){
a[i].x=read();a[i].y=read();a[i].z=read();
a[i].num=1;a[i].ans=0;
}
sort(a+1,a+n+1,cmp);
top=1;
for(int i=2;i<=n;i++){
if(a[i].x==a[i-1].x && a[i].y==a[i-1].y && a[i].z==a[i-1].z)
a[top].num++;
else a[++top]=a[i];
}
CDQ(1,top);
for(int i=1;i<=top;i++)
cnt[a[i].ans+a[i].num-1]+=a[i].num;
for(int i=0;i<n;i++)
printf("%d\n",cnt[i]);
return 0;
}