luogu 3810

https://www.luogu.org/problemnew/show/3810

CDQ分治棵题

第一维 排序

第二维 CDQ分治

第三位 树状数组维护

#include<stdio.h>
#include<algorithm>
#define FOR(i,s,t) for(register int i=s;i<=t;++i)
using std::sort;
const int N=100011;
struct point{
	int x,y,z,sum,cnt;
	inline bool operator ==(const point &B)const{
		return x==B.x&&y==B.y&&z==B.z;
	}
	inline bool operator <(const point &B)const{
		if(x!=B.x)return x<B.x;
		if(y!=B.y)return y<B.y;
		return z<B.z;
	}
	inline bool operator >(const point &B)const{
		if(y!=B.y)return y<B.y;
		return z<=B.z;
	}
}t[N],a[N];
int n,k;
int tr[N<<1],ans[N<<1];
inline void add(int p,int v){
	for(;p<=k;p+=p&(-p))tr[p]+=v;
}
inline int query(int p){
	int ret=0;
	for(;p;p-=p&(-p))ret+=tr[p];
	return ret;
}
inline void del(int p){
	for(;p<=k;p+=p&(-p))
		if(tr[p])tr[p]=0;
		else break;
} 
inline void cdq(int l,int r){
	if(l==r)return;
	int mid=(l+r)>>1;
	int idx1=l,idx2=mid+1;
	cdq(l,mid);cdq(mid+1,r);
	FOR(i,l,r){
		if(idx2>r||(idx1<=mid&&a[idx1]>a[idx2])){
			t[i]=a[idx1++];
			add(t[i].z,t[i].cnt);
		}
		else{
			t[i]=a[idx2++];
			t[i].sum+=query(t[i].z);
		}
	}
	FOR(i,l,r){
		a[i]=t[i];
		del(a[i].z);
	}
	return;
} 
int main(){
	scanf("%d%d",&n,&k);
	FOR(i,1,n)scanf("%d%d%d",&t[i].x,&t[i].y,&t[i].z);
	sort(t+1,t+n+1);
	register int head=1,m=0,tail=0;
	while(head<=n){
		tail=head+1;
		while(tail<=n&&t[head]==t[tail])++tail;
		a[++m]=t[head];a[m].cnt=tail-head;
		head=tail;
	}
	cdq(1,m);
	FOR(i,1,m)
		ans[a[i].sum+a[i].cnt]+=a[i].cnt;
	FOR(i,1,n)
		printf("%d\n",ans[i]);
	return 0;
}

  

posted @ 2017-11-27 21:40  Stump  阅读(134)  评论(0编辑  收藏  举报