548 -- 【模拟试题】陌上花开
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
Hint
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
Hint
1 <= N <= 100,000, 1 <= K <= 200,000
裸三维偏序问题,没学CDQ分治,就只好用树套树了。
这次用的是树状数组,对于这三维,我分为:
1.shape 2.color 3.smell
对于第一维,按形状sort即可,对于第二维,树状数组在做,第三维,树状数组套平衡树,再维护之。
这个平衡树没写splay..
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
struct Splaytree
{
int l,r,fa,num,size,data;
Splaytree()
{
l=r=fa=num=size=data=0;
}
}tree[1000005];
struct Store
{
int s,c,m;
}flower[1000005];
int ct=0,n,k,temp=0;
int same[1000005]={0};
int ans[1000005]={0};
int root[1000005]={0};
// s c m
bool cmp(Store a,Store b)
{
if(a.s==b.s&&a.c==b.c)return a.m<b.m;
if(a.s==b.s)return a.c<b.c;
else return a.s<b.s;
}
int lowbit(int u)
{
return u&(-u);
}
void get(int root,int data)
{
if(root==0)return;//
if(data==tree[root].data){temp+=tree[tree[root].l].size+tree[root].num;return;}//
else if(data>tree[root].data){temp+=tree[tree[root].l].size+tree[root].num;get(tree[root].r,data);}
else get(tree[root].l,data);
}
void ask(int x,int data)
{
for(int i=x;i;i-=lowbit(i))get(root[i],data);
}
void change(int &root,int data)
{
if(root==0){root=++ct;tree[root].data=data;tree[root].size=tree[root].num=1;return;}
tree[root].size++;
if(data==tree[root].data){tree[root].num++;return;}
if(data<tree[root].data)change(tree[root].l,data);
else change(tree[root].r,data);
}
void ins(int x,int data)
{
for(int i=x;i<=k;i+=lowbit(i))change(root[i],data);
}
void solve()
{
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++)scanf("%d%d%d",&flower[i].s,&flower[i].c,&flower[i].m);
sort(flower+1,flower+1+n,cmp);
for(int i=1;i<=n;i++)
{
if(flower[i].s==flower[i+1].s&&flower[i].c==flower[i+1].c&&flower[i].m==flower[i+1].m&&i!=n)same[i+1]=same[i]+1;
else
{
temp=0;
ask(flower[i].c,flower[i].m);
ans[temp]+=same[i]+1;
}
ins(flower[i].c,flower[i].m);
}
for(int i=0;i<n;i++)printf("%d\n",ans[i]);
}
int main(){
solve();
return 0;
}
平衡树里加了个num,表示相同的有几个,就避免了多建相同的点。