其他分享
首页 > 其他分享> > 陌上花开

陌上花开

作者:互联网

今天才学了三维偏序
顺势A了一道模板题
链接:BZOJ 3262

3262: 陌上花开

Time Limit: 20 Sec Memory Limit: 256 MB

Description

有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

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

这是一道裸的板子题
直接套模板
第一维采用sort
第二维采用CDQ分治
第三维采用树状数组(线段树)
一维一维的解决
关于CDQ的入门可参见[CDQ入门]
(https://www.cnblogs.com/orangee/p/10212192.html)

下面是AC代码

解释:
flo数组指一开始读入的数据
wer数组是去重之后的数据
sum数组是树状数组的值
ans数组是该级花的数量及最后输出的东西
结构体里的aga指与该花数值重复的花的数量
注意第一维和第二维sort中的两个cmp条件不同,且要考虑到每种情况

其它的见注释

/**************************************************************
    Problem: 3262
    User: wiiind
    Language: C++
    Result: Accepted
    Time:1996 ms
    Memory:6760 kb
****************************************************************/
 
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
using namespace std;

const int maxn=100001,maxk=200001;
struct sir
{
	int s,c,m,aga,val;
};
sir flo[maxn],wer[maxn];
int sum[maxk],ans[maxk];
int n,k,op=0,num=0;

inline bool cmp1 (const sir &a,const sir &b)
{
	if (a.s==b.s)
	{
		if (a.c==b.c)
			return a.m<b.m;
		return a.c<b.c;
	}
	return a.s<b.s;
}
inline bool cmp2 (const sir &a,const sir &b)
{
	if (a.c==b.c)
		return a.m<b.m;
	return a.c<b.c;
}
inline int lowbit (int x)
{
	return x&(-x);
}
void add (int x,int v)
{
	for (int i=x;i<=k;i+=lowbit (i))
		sum[i]+=v;
}
int ask (int x)
{
	int res=0;
	for (int i=x;i;i-=lowbit (i))
		res+=sum[i];
	return res;
}
void cdq (int l,int r)
{
	if (l==r)
		return ;//递归到底 
	int mid=(l+r)>>1;
	cdq (l,mid);
	cdq (mid+1,r);
	sort (wer+l,wer+mid+1,cmp2); 
	sort (wer+mid+1,wer+r+1,cmp2);//第二维排序 
	int op1=mid+1,op2=l;
	for (;op1<=r;++op1)
	{
		for (;wer[op2].c<=wer[op1].c&&op2<=mid;)
		{
			add (wer[op2].m,wer[op2].aga);
			op2++;
		}//第三维排序 
		wer[op1].val+=ask (wer[op1].m);//累加该花的排名 
	}
	for (int i=l;i<op2;++i)
		add (wer[i].m,-wer[i].aga);//更新树状数组 
}

int main()
{
	scanf ("%d%d",&n,&k);
	for (register int i=1;i<=n;++i)
		scanf ("%d%d%d",&flo[i].s,&flo[i].c,&flo[i].m);
	sort (flo+1,flo+n+1,cmp1);//第一维排序 
	for (register int i=1;i<=n;++i)
	{
		op++;
		if (flo[i].s!=flo[i+1].s||flo[i].c!=flo[i+1].c||flo[i].m!=flo[i+1].m)//去重 
		{
			wer[++num]=flo[i];
			wer[num].aga=op;
			op=0;
		}
	}
	cdq (1,num);
	for (register int i=1;i<=num;++i)
		ans[wer[i].val+wer[i].aga-1]+=wer[i].aga;//一个数值的花对该排名花数量的贡献为该数值的花重复的 
	for (register int i=0;i<n;++i)
		printf ("%d\n",ans[i]);
	return 0;
}

标签:sort,int,陌上,mid,wer,数组,include
来源: https://blog.csdn.net/luowiiind/article/details/99987831