P3810 【模板】三维偏序(陌上花开)题解

Link

P3810 【模板】三维偏序(陌上花开)

Solve

CDQ分治的模板题,第一维直接排序,第二位用递归,第三位用树状数组

实在不懂的小伙伴戳这里浅谈CDQ分治

Code

#include<bits/stdc++.h>
using namespace std;
int N,ans[1000005],K,c[200005],m;
struct AS{
	int a,b,c,cnt,ans;
}a[100005],b[100005];
inline int read(){
	int ret=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-f;ch=getchar();}
	while(ch<='9'&&ch>='0')ret=ret*10+ch-'0',ch=getchar();
	return ret*f;
}
bool cmp1(AS A,AS B){return (A.a<B.a)||(A.a==B.a&&A.b<B.b)||(A.a==B.a&&A.b==B.b&&A.c<B.c);}
bool cmp2(AS A,AS B){return (A.b<B.b)||(A.b==B.b&&A.c<B.c);}
void add_x(int x,int data){
	for(int i=x;i<=K;i+=i&-i)c[i]+=data;
	return ;
}
int get(int x){
	int S=0;
	for(int i=x;i;i-=i&-i)S+=c[i];
	return S;
}
void CDQ(int l,int r){
	if(l==r)return ;
	int mid=(r-l>>1)+l;
	CDQ(l,mid);CDQ(mid+1,r);
	sort(b+l,b+mid+1,cmp2);
	sort(b+mid+1,b+r+1,cmp2);
	int i,j=l;
	for(i=mid+1;i<=r;i++){
		while(b[i].b>=b[j].b&&j<=mid){
			add_x(b[j].c,b[j].cnt);
			j++;
		}
		b[i].ans+=get(b[i].c);
	}
	for(int i=l;i<j;i++)add_x(b[i].c,-b[i].cnt);
}
int main(){
	freopen("CDQ.in","r",stdin);
	freopen("CDQ.out","w",stdout);
	N=read();K=read();
	for(int i=1;i<=N;i++)a[i].a=read(),a[i].b=read(),a[i].c=read();
	sort(a+1,a+1+N,cmp1);
	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[m].cnt++;continue;}
		m++;b[m].a=a[i].a;b[m].b=a[i].b;b[m].c=a[i].c;b[m].cnt++;
	}
	CDQ(1,m);
	for(int i=1;i<=m;i++)ans[b[i].ans+b[i].cnt-1]+=b[i].cnt;
	for(int i=0;i<N;i++)printf("%d\n",ans[i]);
	return 0;
}
posted @ 2020-10-22 14:15  Martian148  阅读(93)  评论(0编辑  收藏  举报