题目链接:点击查看
有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
题解: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
*/