树状数组 之 poj 2481

/*
虽然事先知道这题可用树状数组求解,
但对之前 poj 2352 理解不够深刻啊。。。在被提示可以考虑排序下,才想出办法了。。。
其实和 poj 2352 解法一样,只不过不是那么明显了。
先对 e 进行从大到小排序,
如果 e 相等,对 s 进行从小到大排序。
(对于排序后的Cows,假设 以前的Cows stronger 当前Cow,则必然 当前Cows的s 大于 以前的Cows的s)=>可用树状数组进行维护
但 Wa 了几次次,原因: 
若node[i].s == node[i-1].s, node[i].e == node[i-1].e 时,
则:
(1)两个的 stronger_num 相等,因为不满足 stronger 要求
(题目要求:If Si <= Sj and Ej <= Ei and Ei - Si > Ej - Sj, we say that cowi is stronger than cowj. )
(2)但仍需对树状数组进行更新 (否则,之后的 Cows 的 stronger_num 会少算)
*/
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int MAX_E = 100005;

struct node { int s, e, pos; };
node Arr[MAX_E];
int n, stronger_num[MAX_E], bit[MAX_E];

bool Cmp(const node &n1, const node &n2) {
	if (n1.e == n2.e) return n1.s < n2.s;
	else return n1.e > n2.e;
}

int mySum(int i)
{
	int s = 0;
	while (i) {
		s += bit[i];
		i -= (i & (-i));
	}
	return s;
}

void myAdd(int i)
{
	while (i <= MAX_E) {
		bit[i] += 1;
		i += (i & (-i));
	}
}

void Solve()
{
	for (int i = 1; i <= n; i++) {
		if ((i - 1) > 0 && (Arr[i].s == Arr[i - 1].s) && (Arr[i].e == Arr[i - 1].e)) {
			stronger_num[Arr[i].pos] = stronger_num[Arr[i - 1].pos];
			myAdd(Arr[i].s);
			continue;
		}
		stronger_num[Arr[i].pos] = mySum(Arr[i].s);
		myAdd(Arr[i].s);
	}
	for (int i = 1; i <= n; i++) {
		if (i != 1) printf(" ");
		printf("%d", stronger_num[i]);
	}
	printf("
");
}

int main()
{
	//freopen("input.txt", "r", stdin);
	while (scanf("%d", &n) && n)
	{
		memset(stronger_num, 0, sizeof(stronger_num));
		memset(bit, 0, sizeof(stronger_num));
		int t_s, t_e;
		for (int i = 1; i <= n; i++)
		{
			scanf("%d %d", &t_s, &t_e);
			Arr[i].s = t_s + 1;
			Arr[i].e = t_e + 1;
			Arr[i].pos = i;
		}
		sort(Arr + 1, Arr + (n + 1), Cmp);
		Solve();
	}
}
原文地址:https://www.cnblogs.com/shijianming/p/4140849.html