陌上花开
作者:互联网
今天才学了三维偏序
顺势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