二维偏序,第一维排序,第二维树状数组或CDQ分治。
三维偏序,第一维排序,第二维CDQ分治,第三位CDQ分治或树状数组。
感觉树状数组好写,常数还小点,能用树状数组尽量用。
//KX
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
//unordered_map<int,int>mp;
const int M= 1e5+7;
struct node
{
int a,b,c;
int v,id,ans;
}a[M],b[M];
int ans[M],c[2*M];
const int N = 2e5;
bool cmp1(node a,node b)
{
if(a.a==b.a&&a.b==b.b)return a.c<b.c;
if(a.a==b.a)return a.b<b.b;
return a.a<b.a;
}
bool cmp2(node a,node b)
{
if(a.b==b.b)return a.c<b.c;
return a.b<b.b;
}
void add(int x,int d)
{
while(x<=N)
{
c[x]+=d;
x+=x&(-x);
}
}
int qu(int x)
{
int ret=0;
while(x)
{
ret+=c[x];
x-=x&(-x);
}
return ret;
}
void merge(int l,int r)
{
if(l==r)return ;
int m=(l+r)/2;
merge(l,m),merge(m+1,r);
sort(b+l,b+m+1,cmp2);
sort(b+m+1,b+r+1,cmp2);
int t1=l,t2=m+1;
while(t2<=r)
{
while(t1<=m&&b[t1].b<=b[t2].b)add(b[t1].c,b[t1].v),t1++;
b[t2].ans+=qu(b[t2].c),t2++;
}
for(int i=l;i<t1;i++)//注意 有可能while循环t1没到m,所以这里上限是t1-1.
add(b[i].c,-b[i].v);
}
int main()
{
int n,k;
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++)
scanf("%d%d%d",&a[i].a,&a[i].b,&a[i].c),a[i].id=i,a[i].v=1;
sort(a+1,a+1+n,cmp1);
int sz=0;
a[0].a=a[0].b=a[0].c=0;
for(int i=1;i<=n;i++)
{
if(a[i].a==a[i-1].a&&a[i].b==a[i-1].b&&a[i].c==a[i-1].c)b[sz].v++;
else b[++sz]=a[i],b[sz].id=i;
}
merge(1,sz);
for(int i=1;i<=sz;i++)
{
// printf("i:%d ans:%d v:%d :: %d %d %d\n",i,b[i].ans,b[i].v,b[i].a,b[i].b,b[i].c);
ans[b[i].ans+b[i].v-1]+=b[i].v;//按照题意算贡献,别忘了把重复元素相互间的贡献概念算出来
}
for(int i=0;i<n;i++)
printf("%d\n",ans[i]);
return 0;
}