poj 2481 Cows (树状数组 +1 p2352 妙用加深~)

本文介绍了一个使用树状数组解决的问题——确定每头牛相对于其他牛的强壮程度。通过对牛按照特定条件排序,并利用树状数组高效地计算出每头牛比其强壮的牛的数量。

题意:FJ有n头牛(编号为1~n),每一头牛都有一个测验值[S, E],如果对于牛i和牛j来说,它们的测验值满足下面的条件则证明牛i比牛j强壮:Si <= Sj and Ej <= Ei and Ei - Si > Ej - Sj。现在已知每一头牛的测验值,要求输出每头牛有几头牛比其强壮。

思路:树状数组。需要对牛i比牛j强壮的条件进行理解。把牛群按照测验值E的降序排序,(E相等按S的升序),那么接着就只需考虑S值,如果当前牛的测验值为[s, e],那么比它强壮的牛的个数,就等于排序在它前面的,S值在[0,s]区间的牛数量(E相等的话为[0,s-1])。下面的就是树状数组部分了。

/*
    Subject: 树状数组 
    Sample : poj 2481 Cows -- p2352
*/
#include <iostream>
#include <cstring>
#include <vector>
#include <cstdlib>
#include <queue>
#include <algorithm>
#define Bug cout << "here\n";

using namespace std;
const int N = 100005;

int n, T, k;
int f[N];
int cnt[N];
int B[N];
struct node {
	int x, y;
	int id;
}p[N];

bool cmp(const node a, const node b) {
	if(a.y != b.y) return a.y > b.y;
	return a.x < b.x;
}
int lowbit(int x) {
    return x & (-x);
}

void add(int i, int x) {
    while(i <= N) { // 注意, 不是 n, 是 N 
        B[i] += x;
        i = i + lowbit(i);
    }
} //得到 Bn

long long getsum(int i) {
    long long sum = 0;
    while(i > 0) {
        sum += B[i];
        i = i - lowbit(i);
    }
    return sum;
}
int main() {
    int i;    
    while(scanf("%d", &n) == 1 && n) {
    	memset(cnt, 0, sizeof(cnt));
    	memset(B, 0, sizeof(B));
    	memset(f, 0, sizeof(f));
    	for(i = 0; i < n; i++) {
			scanf("%d%d", &p[i].x, &p[i].y);
			p[i].id = i;
		}
		sort(p, p+n, cmp);
		for(i = 0; i < n; i++) {
			if(i > 0 && p[i].x == p[i-1].x && p[i].y == p[i-1].y) {
				f[p[i].id] = f[p[i-1].id];
			}
			else f[p[i].id] = getsum(p[i].x+1);
			add(p[i].x+1, 1);
		}
		for(i = 0; i < n; i++) {
			if(i == 0) cout << f[i];
			else cout << ' ' << f[i];
		}
		cout << endl;		
	}
	//system("pause");
    return 0;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值