题目大意:
有n朵花,每朵花有三个属性:花形(s)、颜色(c)、气味(m),用三个整数表示。
现在要对每朵花评级,一朵花的级别是它拥有的美丽能超过的花的数量。
定义一朵花A比另一朵花B要美丽,当且仅Sa>=Sb,Ca>=Cb,Ma>=Mb。
显然,两朵花可能有同样的属性。需要统计出评出每个等级的花的数量。
思路:
典型的一道三维偏序的题目,作为一道cdq分治的入门题。
第一维上排序,第二维上cdq分治,第三维上树状数组。感觉这个不同的维度的处理就是不断地降维同时不断地筛选的过程。
有一个地方需要注意的是,三个属性满足要求的情况都是大于等于,需要注意等号的处理。只按照第一维排序显然是不可以的,这样在第一维相等的情况下后面的三元组就默认为第一维不满足条件了,这样排在前面的三元组无法处理到后面的情况,所以排序的时候还是要按照三个维度来排序。最后还有注意有完全相同的三元组,计算答案的时候因为顺序的先后导致了答案的不同,所以最后对于完全相同的三元组以最大的答案来更新所有的答案。
/*=========================
* Author : ylsoi
* Problem : bzoj3262
* Algorithm : cdq
* Time : 2018.7.30
* =======================*/
#include<bits/stdc++.h>
#define REP(i,a,b) for(int i=a;i<=b;++i)
#define mid ((l+r)>>1)
typedef long long ll;
using namespace std;
void File(){
freopen("bzoj3262.in","r",stdin);
freopen("bzoj3262.out","w",stdout);
}
const int maxn=1e5+10;
int n,k,m,sum[maxn],cnt[maxn];
map<int,int>mp;
map<int,int>::iterator it;
struct node{int x,y,z,ans;}a[maxn],tmp[maxn];
bool cmp1(node xx,node yy){
if(xx.x!=yy.x)return xx.x<yy.x;
else if(xx.y!=yy.y)return xx.y<yy.y;
else if(xx.z!=yy.z)return xx.z<yy.z;
else return xx.ans>yy.ans;
}
int lowbit(int x){return x&(-x);}
void modify(int pos,int x){
while(pos<=m){
sum[pos]+=x;
pos+=lowbit(pos);
}
}
int query(int pos){
int ret=0;
while(pos>=1){
ret+=sum[pos];
pos-=lowbit(pos);
}
return ret;
}
void cdq(int l,int r){
if(l==r)return;
cdq(l,mid); cdq(mid+1,r);
int p=l,pl=l,pr=mid+1;
while(pl<=mid && pr<=r){
if(a[pl].y<=a[pr].y){
modify(a[pl].z,1);
tmp[p++]=a[pl++];
}
else{
a[pr].ans+=query(a[pr].z);
tmp[p++]=a[pr++];
}
}
if(pl<=mid){
REP(i,l,pl-1)modify(a[i].z,-1);
while(pl<=mid)tmp[p++]=a[pl++];
}
else{
while(pr<=r){
a[pr].ans+=query(a[pr].z);
tmp[p++]=a[pr++];
}
REP(i,l,mid)modify(a[i].z,-1);
}
REP(i,l,r)a[i]=tmp[i];
}
void init(){
scanf("%d%d",&n,&k);
REP(i,1,n){
scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].z);
mp.insert((pair<int,int>){a[i].z,0});
}
for(it=mp.begin(),m=1;it!=mp.end();++it,++m)
mp[it->first]=m;
REP(i,1,n)a[i].z=mp[a[i].z];
sort(a+1,a+n+1,cmp1);
}
int main(){
File();
init();
cdq(1,n);
sort(a+1,a+n+1,cmp1);
REP(i,1,n)if(i!=1 && a[i].x==a[i-1].x && a[i].y==a[i-1].y && a[i].z==a[i-1].z)
a[i].ans=a[i-1].ans;
REP(i,1,n)++cnt[a[i].ans];
REP(i,0,n-1)printf("%d\n",cnt[i]);
return 0;
}