给出
n
≤
1
e
5
n\leq1e5
n≤1e5个三元组
(
a
i
,
b
i
,
c
i
)
(a_i,b_i,c_i)
(ai,bi,ci),满足三元组
i
i
i比三元组
j
j
j美丽的条件是
a
i
>
a
j
,
b
i
>
b
j
,
c
i
>
c
j
a_i>a_j,b_i>b_j,c_i>c_j
ai>aj,bi>bj,ci>cj,然后求问比
i
i
i朵花美丽的的数量各是多少。
三维偏序。先对
x
x
x排序,考虑左区间和右区间的时候,再对
y
y
y排序,对于右边
y
y
y,用树状数组维护所有比
y
y
y小的那一部分的
z
z
z。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const ll INF=LONG_LONG_MAX;
const int N=1e5+5;
const int M=2e5+2;
int ans[N];
struct node{ int x,y,z,cnt,ans; }a[N];
bool cmpx(node a,node b) {
if(a.x!=b.x) return a.x<b.x;
if(a.y!=b.y) return a.y<b.y;
return a.z<b.z;
}
bool cmpy(node a,node b) {
if(a.y!=b.y) return a.y<b.y;
return a.z<b.z;
}
struct BIT{
int tr[M];
int n;
int lowbit(int x) {
return x&(-x);
}
void add(int x,int k) {
while(x<=n) {
tr[x]+=k;
x+=lowbit(x);
}
}
int query(int x) {
int sum=0;
while(x>0) {
sum+=tr[x];
x-=lowbit(x);
}
return sum;
}
}Tree;
void CDQ(int l,int r) {
if(l==r) {
a[l].ans+=a[l].cnt-1;
return;
}
int mid=(l+r)>>1;
CDQ(l,mid);CDQ(mid+1,r);
sort(a+l,a+1+mid,cmpy);
sort(a+mid+1,a+r+1,cmpy);
int j=l;
for(int i=mid+1;i<=r;i++) {
for(;a[j].y<=a[i].y&&j<=mid;j++)
Tree.add(a[j].z,a[j].cnt);
a[i].ans+=Tree.query(a[i].z);
}
for(int i=l;i<=j-1;i++) Tree.add(a[i].z,-a[i].cnt);
}
int main() {
int n,k;
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++) {
scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].z);
a[i].ans=1;
}
sort(a+1,a+1+n,cmpx);
int tot=0;
for(int i=1;i<=n;i++) {
if(i!=1&&a[i-1].x==a[i].x&&a[i-1].y==a[i].y&&a[i-1].z==a[i].z) a[tot].cnt++;
else a[++tot]=a[i],a[tot].cnt=1;
}
Tree.n=k;
CDQ(1,tot);
for(int i=1;i<=tot;i++) ans[a[i].ans]+=a[i].cnt;
for(int i=1;i<=n;i++) printf("%d\n",ans[i]);
return 0;
}