bzoj3262:陌上花开

传送门

典型的三维偏序,cdq分治
由于相同的花之间也会产生贡献,考虑将相同的花合并来做
代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
void read(int &x) {
	char ch; bool ok;
	for(ok=0,ch=getchar(); !isdigit(ch); ch=getchar()) if(ch=='-') ok=1;
	for(x=0; isdigit(ch); x=x*10+ch-'0',ch=getchar()); if(ok) x=-x;
}
#define rg register
#define lowbit(i) (i&(-i))
const int maxn=1e5+10,maxm=2e5+10;
int n,m,ans[maxn],f[maxm];
struct oo{int id,x,y,z,ans,cnt;}a[maxn];
bool cmp(oo a,oo b){return a.x==b.x?(a.y==b.y?a.z<b.z:a.y<b.y):a.x<b.x;}
bool cmp1(oo a,oo b){return a.y==b.y?a.id<b.id:a.y<b.y;}
void add(int x,int y){for(rg int i=x;i<=m;i+=lowbit(i))f[i]+=y;}
int get(int x){int ans=0;for(rg int i=x;i;i-=lowbit(i))ans+=f[i];return ans;}
void cdq(int l,int r)
{
	if(l==r)return ;
	int mid=(l+r)>>1;
	cdq(l,mid),cdq(mid+1,r);
	sort(a+l,a+r+1,cmp1);
	for(rg int i=l;i<=r;i++)
		if(a[i].id<=mid)add(a[i].z,1);
		else a[i].ans+=get(a[i].z);
	for(rg int i=l;i<=r;i++)
		if(a[i].id<=mid)add(a[i].z,-1);
}
int main()
{
	read(n),read(m);
	for(rg int i=1;i<=n;i++)read(a[i].x),read(a[i].y),read(a[i].z);
	sort(a+1,a+n+1,cmp);
	for(rg int i=1;i<=n;i++)a[i].id=i;
	cdq(1,n);
	for(rg int i=1;i<=n;i++)ans[a[i].ans]++;
	for(rg int i=0;i<n;i++)printf("%d\n",ans[i]);
}
posted @ 2019-02-22 17:14  蒟蒻--lichenxi  阅读(85)  评论(0编辑  收藏  举报