陌上花开 模板 三维偏序

陌上花开 模板 三维偏序

题目描述

\(n\)朵花,每朵花有三个属性:花形\((s)\)、颜色\((c)\)、气味\((m)\),用三个整数表示。
现在要对每朵花评级,一朵花的级别是它拥有的美丽能超过的花的数量。
定义一朵花\(A\)比另一朵花\(B\)要美丽,当且仅$ Sa \geq Sb,Ca \geq Cb,Ma \geq Mb$。显然,两朵花可能有同样的属性。需要统计出评出每个等级的花的数量。

输入格式

第一行为\(N,K (1 <= N <= 100,000, 1 <= K <= 200,000 )\), 分别表示花的数量和最大属性值。
以下\(N\)行,每行三个整数\(si, ci, mi (1 <= si, ci, mi <= K)\),表示第\(i\)朵花的属性

输出格式

包含\(N\)行,分别表示评级为\(0...N-1\)的每级花的数量。

样例

样例输入

10 3
3 3 3
2 3 3
2 3 1
3 1 1
3 1 2
1 3 1
1 1 2
1 2 2
1 3 2
1 2 1

样例输出

3
1
3
0
1
0
1
0
0
1

分析

\(CDQ\)分治套数状数组

代码

#include<cstdio>
#include<algorithm>
inline int read(){
	int x=0,fh=1;
	char ch=getchar();
	while(ch<'0' || ch>'9'){
		if(ch=='-') fh=-1;
		ch=getchar();
	}
	while(ch>='0' && ch<='9'){
		x=(x<<1)+(x<<3)+(ch^48);
		ch=getchar();
	}
	return x*fh;
}
const int maxn=1e6+5;
struct asd{
	int a,b,c,id,cnt;
}jl[maxn],f[maxn];
bool cmp1(asd aa,asd bb){
	if(aa.a==bb.a && aa.b==bb.b) return aa.c<bb.c;
	if(aa.a==bb.a) return aa.b<bb.b;
	return aa.a<bb.a;
}
bool cmp2(asd aa,asd bb){
	if(aa.b==bb.b) return aa.c<bb.c;
	return aa.b<bb.b;
}
int n,k,ans[maxn],tr[maxn],anss[maxn];
int lb(int xx){
	return xx&-xx;
}
void ad(int wz,int val){
	for(int i=wz;i<maxn;i+=lb(i)){
		tr[i]+=val;
	}
}
int qh(int wz){
	int nans=0;
	for(int i=wz;i>0;i-=lb(i)){
		nans+=tr[i];
	}
	return nans;
}
void solve(int l,int r){
	if(l==r) return;
	int mids=(l+r)>>1;
	solve(l,mids);
	solve(mids+1,r);
	std::sort(f+l,f+mids+1,cmp2);
	std::sort(f+mids+1,f+r+1,cmp2);
	int now=l;
	for(int i=mids+1;i<=r;i++){
		while(f[now].b<=f[i].b && now<=mids){
			ad(f[now].c,f[now].cnt);
			now++;
		}
		ans[f[i].id]+=qh(f[i].c);
	}
	for(int i=now-1;i>=l;i--) ad(f[i].c,-f[i].cnt);
}
int main(){
	n=read(),k=read();
	for(int i=1;i<=n;i++){
		jl[i].a=read(),jl[i].b=read(),jl[i].c=read();
		jl[i].id=i;
	}
	std::sort(jl+1,jl+1+n,cmp1);
	int nn=n,js=0;
	n=0;
	for(int i=1;i<=nn;i++){
		js++;
		if(jl[i].a!=jl[i+1].a || jl[i].b!=jl[i+1].b || jl[i].c!=jl[i+1].c){
			f[++n]=jl[i];
			f[n].cnt=js;
			js=0;
		}
	}
	solve(1,n);
	for(int i=1;i<=n;i++){
		anss[ans[f[i].id]+f[i].cnt-1]+=f[i].cnt;
	}
	for(int i=0;i<nn;i++){
		printf("%d\n",anss[i]);
	}
	return 0;
}

posted @ 2020-09-07 15:55  liuchanglc  阅读(123)  评论(0编辑  收藏  举报