BSOJ4548:陌上花开 树状数组套平衡树(基础题)

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

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,表示相同的有几个,就避免了多建相同的点。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值