Bzoj【3262】陌上花开

版权声明:转载记得声明噢! https://blog.csdn.net/Richard__Luan/article/details/81393593

传送门biu~

CDQ分治第一题。。。上次集训还认为是大神的东西,没想到现在就学了。。。

CDQ分治可以看做降维打击,大体思路是先把一段区间分为两部分,只考虑左半部分对右半部分的影响,常数小还好写,可以顶替复杂高级数据结构,只是必须离线

AC Code

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
struct flower
{
	int x,y,z;
	int cnt,ans;
}a[1000005];
int c[3000005],n,k,tot,num[1000005];
bool cmp(flower a,flower b)
{
	if(a.x<b.x) return 1;
	if(a.x>b.x) return 0;
	if(a.y<b.y) return 1;
	if(a.y>b.y) return 0;
	if(a.z<b.z) return 1;
	return 0;
}
bool cmp2(flower a,flower b)
{
	if(a.y<b.y) return 1;
	if(a.y>b.y) return 0;
	if(a.z<b.z) return 1;
	if(a.z>b.z) return 0;
	if(a.x<b.x) return 1;
	return 0;
}
inline int lowbit(int x)
{
	return x&(-x);
}
void add(int x,int y)
{
	while(x<=k)
	{
		c[x]+=y;
		x+=lowbit(x);
	}
}
int ask(int x)
{
	int ans=0;
	while(x)
	{
		ans+=c[x];
		x-=lowbit(x);
	}
	return ans;
}
void CDQ(int l,int r)
{
	if(l==r)
	{
	a[l].ans+=a[l].cnt-1;
	return ;	
	}
	int mid=(l+r)>>1;
	CDQ(l,mid);
	CDQ(mid+1,r);
	sort(a+l,a+1+mid,cmp2);
	sort(a+mid+1,a+r+1,cmp2);
	int j=l;
	for(int i=mid+1;i<=r;i++)
	{
		while(j<=mid&&a[j].y<=a[i].y)add(a[j].z,a[j].cnt),j++;
		a[i].ans+=ask(a[i].z);
	}
	for(int i=l;i<j;i++)
	add(a[i].z,-a[i].cnt);
}
int main()
{
	scanf("%d%d",&n,&k);
	for(int i=1;i<=n;i++)
	{
		scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].z),a[i].ans=1;
	}
	sort(a+1,a+1+n,cmp);
	for(int i=1;i<=n;i++)
	if(i!=1&&a[i].x==a[i-1].x&&a[i].y==a[i-1].y&&a[i].z==a[i-1].z)a[tot].cnt++;
	else a[++tot]=a[i],a[tot].cnt=1;
	CDQ(1,tot);
	sort(a+1,a+tot+1,cmp);
	for(int i=1;i<=tot;i++)num[a[i].ans]+=a[i].cnt;
	for(int i=1;i<=n;i++)printf("%d\n",num[i]);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/Richard__Luan/article/details/81393593