HYSBZ - 3262 陌上花开 CDQ分治

题目链接:点击查看

有n朵花,每朵花有三个属性:花形(s)、颜色(c)、气味(m),用三个整数表示。

现在要对每朵花评级,一朵花的级别是它拥有的美丽能超过的花的数量。

定义一朵花A比另一朵花B要美丽,当且仅Sa>=Sb,Ca>=Cb,Ma>=Mb。

显然,两朵花可能有同样的属性。需要统计出评出每个等级的花的数量。

Input

第一行为N,K (1 <= N <= 100,000, 1 <= K <= 200,000 ), 分别表示花的数量和最大属性值。

以下N行,每行三个整数si, ci, mi (1 <= si, ci, mi <= K),表示第i朵花的属性

Output

包含N行,分别表示评级为0...N-1的每级花的数量。

Sample Input

扫描二维码关注公众号,回复: 5958054 查看本文章

10 3 3 3 3 2 3 3 2 3 1 3 1 1 3 1 2 1 3 1 1 1 2 1 2 2 1 3 2 1 2 1

Sample Output

3 1 3 0 1 0 1 0 0 1

题解:CDQ分治,三维偏序,先按s排序,然后在按c,在用树状数组求比m小的即可,要注意的是存在三个值都一样了,本想标记来着,结果失败告终,所以还是预处理一下,去重,一样的增加到val即可,还一个注意的点就是,区间只有一个时的处理。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

#define lowbit(x) x&(-x)
const int N=100010+10;
struct node{
	int op;
	int si,ci,mi;
	int id;
	int val;
}q[N],tmp[N],a[N];
int n,m,len;
int ans[N];
int num[N];
int book[N];
int cmp(node x,node y)
{
	if(x.si!=y.si)return x.si<y.si;
	else if(x.ci!=y.ci) return x.ci<y.ci;
	else return x.mi<y.mi;
}
int sum[N*2];
void update(int x,int val)
{
	if(x==0)return;
	while(x<=200000)
	{
		sum[x]+=val;
		x+=lowbit(x);
	}
}
int query(int x)
{
	int res=0;
	while(x)
	{
		res+=sum[x];
		x-=lowbit(x);
	}
	return res;
}
void sum_clear(int x)
{
	if(x==0)return;
	while(x<=200000)
	{
		sum[x]=0;
		x+=lowbit(x);
	}
}

void CDQ(int l,int r)
{
	if(r-l<=1)
    {
        ans[q[l].id]=book[q[l].id]-1;
        return;
    }
	int mid=(r+l)>>1;CDQ(l,mid);CDQ(mid,r);
	int ll=l,rr=mid;
	int cnt=0;
	while(ll<mid&&rr<r)
	{
		if(q[ll].ci<=q[rr].ci)
		{
			update(q[ll].mi,q[ll].val);
			tmp[cnt++]=q[ll++];
		}
		else
		{
			ans[q[rr].id]+=query(q[rr].mi);
			tmp[cnt++]=q[rr++];
		}
	}
	while(ll<mid) tmp[cnt++]=q[ll++];
	while(rr<r)
	{
		ans[q[rr].id]+=query(q[rr].mi);
		tmp[cnt++]=q[rr++];
	}
	for(int i=0;i<cnt;i++)
	{
		q[i+l]=tmp[i];
		sum_clear(tmp[i].mi);
	}
}

int main()
{
	int x,y,z;
	while(~scanf("%d%d",&n,&m))
	{
		len=0;
		for(int i=1;i<=n;i++)
		{
			scanf("%d%d%d",&x,&y,&z);
			a[i].si=x;
			a[i].ci=y;
			a[i].mi=z;
			num[i]=0;
			ans[i]=0;
			book[i]=0;
		}
		ans[0]=0;
		num[0]=0;
		book[0]=0;
		sort(a+1,a+1+n,cmp);
		for(int i=1;i<=n;i++)
		{
			if(a[i].si==a[i-1].si&&a[i].mi==a[i-1].mi&&a[i].ci==a[i-1].ci)
			{
				book[q[len-1].id]++;
				q[len-1].val++;
				continue;
			}
			q[len].id=i;
			q[len].si=a[i].si;
			q[len].ci=a[i].ci;
			q[len].mi=a[i].mi;
			q[len].val=1;
			book[q[len].id]=1;
			len++;
		}
		CDQ(0,len);
		for(int i=1;i<=n;i++) num[ans[i]]+=book[i];
		for(int i=0;i<n;i++) printf("%d\n",num[i]);
	}

	return 0;
}
/*
7 5
1 1 1
2 2 2
4 4 4
2 2 2
3 3 3
4 4 4
4 4 4

5 5
4 4 4
4 4 4
4 4 4
4 4 4
4 4 4
*/

猜你喜欢

转载自blog.csdn.net/mmk27_word/article/details/89344548
今日推荐