BZOJ 3262 陌上花开 CDQ分治

题目大意:给定一堆花,每个花有三个属性,定义一朵花比另一朵花美丽当期仅当三个值都大于等于另一朵花 定义花的评级为没有它美丽的花的数量 求评级为0~N-1的花的数量

CDQ分治的题,之前在HZWER神犇的博客里见到过,就写了写,今天BZ活了想去交才发现原来是只有会员才知道的世界。。。还好学校的大神有BZ的会员,借号交了下,半天过不去,最后发现原来我CDQ分治写脑残了。。。。妈妈再也不用担心我的学习了。。。

第一维排序,第二维CDQ分治,第三维树状数组,这题就切了

注意当两朵花的三个属性均相同两朵花互相比对方美丽 这个时候需要把这两朵花合并在一起处理 我这里还写挂了0.0 伤不起啊

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define M 100100
using namespace std;
struct abcd{
	int x,y,z;
	int cnt,ans;
}a[M],na[M];
bool operator < (const abcd &x,const abcd &y)
{
	if(x.x==y.x)
	{
		if(x.y==y.y)
			return x.z<y.z;
		return x.y<y.y;
	}
	return x.x<y.x;
}
bool cmp(const abcd &x,const abcd &y)
{
	if(x.y==y.y)
	{
		if(x.z==y.z)
			return x.x<y.x;
		return x.z<y.z;
	}
	return x.y<y.y;
}
int n,m,tot,T;
int ans[M];
int c[M<<1],tim[M<<1];
void update(int x,int y)
{
	for(;x<=m;x+=x&-x)
	{
		if(tim[x]!=T)
			c[x]=0;
		tim[x]=T;
		c[x]+=y;
	}
}
int getans(int x)
{
	int re=0;
	for(;x;x-=x&-x)
		if(tim[x]==T)
			re+=c[x];
	return re;
}
void CDQ(int l,int r)
{
	int i,j,mid=l+r>>1;
	if(l==r)
	{
		a[mid].ans+=a[mid].cnt-1;
		return ;
	}
	int l1=l,l2=mid+1;
	for(i=l;i<=r;i++)
	{
		if(a[i].x<=mid)
			na[l1++]=a[i];
		else
			na[l2++]=a[i];
	}
	memcpy( a+l , na+l , sizeof(a[0])*(r-l+1) );
	CDQ(l,mid);
	j=l;++T;
	for(i=mid+1;i<=r;i++)
	{
		for(;j<=mid&&a[j].y<=a[i].y;j++)
			update(a[j].z,a[j].cnt);
		a[i].ans+=getans(a[i].z);
	}
	CDQ(mid+1,r);
	l1=l;l2=mid+1;
	for(i=l;i<=r;i++)
	{
		if( ( cmp(a[l1],a[l2]) || l2>r ) && l1<=mid )
			na[i]=a[l1++];
		else
			na[i]=a[l2++];
	}
	memcpy( a+l , na+l , sizeof(a[0])*(r-l+1) );
}
int main()
{
	int i;
	cin>>n>>m;
	for(i=1;i<=n;i++)
		scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].z),a[i].cnt++;
	sort(a+1,a+n+1);
	for(i=1;i<=n;i++)
	{
		if( i==1 || a[i-1]<a[i] )
			a[++tot]=a[i];
		else
			a[tot].cnt++;
	}
	for(i=1;i<=tot;i++)
		a[i].x=i;
	sort(a+1,a+tot+1,cmp);
	CDQ(1,tot);
	for(i=1;i<=tot;i++)
		ans[ a[i].ans ]+=a[i].cnt;
	for(i=0;i<n;i++)
		printf("%d\n",ans[i]);
}


你可能感兴趣的:(树状数组,bzoj,cdq分治,BZOJ3262)