https://www.lydsy.com/JudgeOnline/problem.php?id=3262
题意:n朵花,每朵花有3个属性a,b,c,一朵花比另一朵花美丽当且仅当3个属性都大于等于另一朵,一朵花比x朵花美丽则称其等级为x,求出每个等级的花的数量。
思路:三维偏序问题,cdq分治模板
https://zhuanlan.zhihu.com/p/55322598这个讲解不错。
#include<bits/stdc++.h>
using namespace std;
#define lowbit(x) (x&(-x))
#define maxn 200000+100
int n,k,c[maxn],cnt,ans[maxn];
struct Element{
int a,b,c,w,f;
bool operator < (Element x)const{
if(a!=x.a)return a<x.a;
if(b!=x.b)return b<x.b;
return c<x.c;
}
}e[maxn],t[maxn];
int sum(int x)
{
int ret=0;
while(x)
{
ret+=c[x];
x-=lowbit(x);
}
return ret;
}
void add(int x,int d)
{
while(x<=k)
{
c[x]+=d;
x+=lowbit(x);
}
}
void CDQ(int l,int r)
{
if(l==r)return;
int mid=(l+r)/2;
CDQ(l,mid);
CDQ(mid+1,r);
int p=l,q=mid+1,x=l;
while(p<=mid || q<=r)
{
if(q>r || p<=mid && e[p].b<=e[q].b)add(e[p].c,e[p].w),t[x++]=e[p++];
else e[q].f+=sum(e[q].c),t[x++]=e[q++];//这里切记两句不可颠倒,因为前一句对e[q]有改动。
}
for(x=l;x<=mid;x++)add(e[x].c,-e[x].w);
for(x=l;x<=r;x++)e[x]=t[x];
}
int main()
{
//freopen("input.in","r",stdin);
cin>>n>>k;
for(int i=1;i<=n;i++)scanf("%d%d%d",&e[i].a,&e[i].b,&e[i].c),e[i].w=1;
sort(e+1,e+1+n);
for(int i=1;i<=n;i++)
{
if(e[i].a==e[cnt].a&&e[i].b==e[cnt].b&&e[i].c==e[cnt].c)e[cnt].w++;
else e[++cnt]=e[i];
}
CDQ(1,cnt);
for(int i=1;i<=cnt;i++)ans[e[i].f+e[i].w-1]+=e[i].w;
for(int i=0;i<n;i++)printf("%d\n",ans[i]);
return 0;
}