POJ 2481 Cows

题目大意:

        现有多个测例,每个测例中给出N段闭区间[si, ei](测例以N = 0结束,1 ≤ N ≤ 10^5),si和ei的范围为[1, 10^5],如果两区间[si, ei]和[sj, ej]满足si ≤ sj且ej ≤ ei且ei - si > ej - sj,则成前一个区间大于后一个区间,现要求对于每个测例,都按输入的顺序输出每个区间的比它大区间的数量。

题目链接

注释代码:

/*                          
 * Problem ID : POJ 2481 Cows
 * Author     : Lirx.t.Una                          
 * Language   : C              
 * Run Time   : 922 ms                          
 * Run Memory : 2480 KB                          
*/ 

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>

//区间最大数量
#define	MAXN	100000

using namespace std;

struct	Intv {//interval,闭区间

	int		s, e;//区间的左右端点
	int		id;//区间的id,记录区间的输入顺序

	bool//对区间按照右端点从大到小排列,如果右端点相等则按照左端点从小到大排列
	operator<(const Intv &oth)
	const {

		if ( e == oth.e ) return s < oth.s;
		return e > oth.e;
	}
};

Intv	inv[MAXN];//区间
int		ans[MAXN];//按照输入顺序存放最终结果,每个区间大于它的区间数量

//对inv排好序后,后一个区间的右端点一定小于等于前一个区间,而根据题目要求,只要找到之前左端点小于等于当前区间的区间数量即可,但是需要分情况讨论
//考虑特殊情况,如果后以区间右端点等于前一区间的右端点,则需要找左端点小于当前区间左端点的区间数量
 //但实际上,该如果当前区间左端点也等于前移区间左端点则其ans值和前移区间相同,对于其余情况就直接求左端点小于等于当前区间的数量即可

int		c[MAXN + 1];//对区间的s域建立树状数组
int		lowbit[MAXN + 1];

int		n;//区间数量

void
update(int x) {

	while ( x <= n ) {//s域的最大值也是MAXN
	
		c[x]++;
		x += lowbit[x];
	}
}

int
query(int x) {

	int		sum;

	sum = 0;
	while ( x > 0 ) {
	
		sum += c[x];
		x   -= lowbit[x];
	}

	return sum;
}

int
main() {

	int		i;

	for ( i = 1; i <= MAXN; i++ ) lowbit[i] = i & -i;

	while ( scanf("%d", &n), n ) {
	
		memset(c, 0, sizeof(c));
		for ( i = 0; i < n; i++ ) {
		
			inv[i].id = i;
			scanf("%d%d", &inv[i].s, &inv[i].e);
			inv[i].s++;//树状数组
		}
		sort(inv, inv + n);

		//先处理第一个区间
		ans[ inv[0].id ] = 0;
		update( inv[0].s );
		for ( i = 1; i < n; i++ ) {

			//剩下的分情况讨论
			if ( inv[i].e == inv[i - 1].e && inv[i].s == inv[i - 1].s )
				ans[ inv[i].id ] = ans[ inv[i - 1].id ];
			else
				ans[ inv[i].id ] = query( inv[i].s );

			update( inv[i].s );
		}

		printf("%d", *ans);
		for ( i = 1; i < n; i++ ) printf(" %d", ans[i]);
		putchar('\n');
	}

	return 0;
}
无注释代码:

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>

#define	MAXN	100000

using namespace std;

struct	Intv {

	int		s, e;
	int		id;

	bool
	operator<(const Intv &oth)
	const {

		if ( e == oth.e ) return s < oth.s;
		return e > oth.e;
	}
};

Intv	inv[MAXN];
int		ans[MAXN];

int		c[MAXN + 1];
int		lowbit[MAXN + 1];

int		n;

void
update(int x) {

	while ( x <= n ) {
	
		c[x]++;
		x += lowbit[x];
	}
}

int
query(int x) {

	int		sum;

	sum = 0;
	while ( x > 0 ) {
	
		sum += c[x];
		x   -= lowbit[x];
	}

	return sum;
}

int
main() {

	int		i;

	for ( i = 1; i <= MAXN; i++ ) lowbit[i] = i & -i;

	while ( scanf("%d", &n), n ) {
	
		memset(c, 0, sizeof(c));
		for ( i = 0; i < n; i++ ) {
		
			inv[i].id = i;
			scanf("%d%d", &inv[i].s, &inv[i].e);
			inv[i].s++;
		}
		sort(inv, inv + n);

		ans[ inv[0].id ] = 0;
		update( inv[0].s );
		for ( i = 1; i < n; i++ ) {

			if ( inv[i].e == inv[i - 1].e && inv[i].s == inv[i - 1].s )
				ans[ inv[i].id ] = ans[ inv[i - 1].id ];
			else
				ans[ inv[i].id ] = query( inv[i].s );

			update( inv[i].s );
		}

		printf("%d", *ans);
		for ( i = 1; i < n; i++ ) printf(" %d", ans[i]);
		putchar('\n');
	}

	return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值