3262: 陌上花开

3262: 陌上花开

Time Limit: 20 Sec   Memory Limit: 256 MB
Submit: 1423   Solved: 640
[ Submit][ Status][ Discuss]

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

Source

[ Submit][ Status][ Discuss]



排序一维

树状数组一维

线段树一维

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;

const int maxn = 2E5 + 20;
const int T = 100;

struct data{
	int a,b,c,Num;
	data(){}
	data(int a,int b,int c,int Num): a(a),b(b),c(c),Num(Num){}
	bool operator < (const data &B) const {
		return a < B.a;
	}
}f[maxn];

int n,m,cnt,Root[maxn],lc[maxn*T],rc[maxn*T],c[maxn*T],rank[maxn],ans[maxn];

int Getlc(int o) {return lc[o]?lc[o]:lc[o] = ++cnt;}
int Getrc(int o) {return rc[o]?rc[o]:rc[o] = ++cnt;}

int Query(int o,int l,int r,int ql,int qr)
{
	if (ql <= l && r <= qr) return c[o];
	if (!o) return 0;
	int mid = (l + r) >> 1,ret = 0;
	if (ql <= mid) ret += Query(lc[o],l,mid,ql,qr);
	if (qr > mid) ret += Query(rc[o],mid + 1,r,ql,qr);
	return ret;
}

void Insert(int o,int l,int r,int pos)
{
	if (l == r) {
		++c[o];
		return;
	}
	int mid = (l + r) >> 1;
	if (pos <= mid) Insert(Getlc(o),l,mid,pos);
	else Insert(Getrc(o),mid + 1,r,pos);
	c[o] = c[lc[o]] + c[rc[o]];
}

int getint()
{
	char ch = getchar();
	int ret = 0;
	while (ch < '0' || '9' < ch) ch = getchar();
	while ('0' <= ch && ch <= '9')
		ret = ret*10 + ch - '0',ch = getchar();
	return ret;
}

int main()
{
	#ifdef DMC
		freopen("DMC.txt","r",stdin);
	#endif
	
	n = getint(); m = getint();
	for (int i = 1; i <= n; i++) {
		int a,b,c;
		a = getint();
		b = getint();
		c = getint();
		f[i] = data(a,b,c,i);
	}
	sort(f + 1,f + n + 1);
	int L = 1;
	for (int i = 1; i <= n + 1; i++) {
		if (f[i].a != f[i-1].a && i > 1) {
			for (int j = L; j < i; j++) {
				for (int l = f[j].b; l > 0; l -= l&-l)
					rank[f[j].Num] += Query(Root[l],1,m,1,f[j].c);
				--rank[f[j].Num];
			}
			L = i;
		}
		if (i == n + 1) break;
		for (int j = f[i].b; j <= m; j += j&-j) {
			if (!Root[j]) Root[j] = ++cnt;
			Insert(Root[j],1,m,f[i].c);
		}
	}
	for (int i = 1; i <= n; i++) ++ans[rank[i]];
	for (int i = 0; i < n; i++)
		printf("%d\n",ans[i]);
	return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值