#樹狀陣列# POJ 2481 Cows
Description
Farmer John's cows have discovered that the clover growing along the ridge of the hill (which we can think of as a one-dimensional number line) in his field is particularly good.
Farmer John has N cows (we number the cows from 1 to N). Each of Farmer John's N cows has a range of clover that she particularly likes (these ranges might overlap). The ranges are defined by a closed interval [S,E].
But some cows are strong and some are weak. Given two cows: cowi and cowj, their favourite clover range is [Si, Ei] and [Sj, Ej]. If Si <= Sj and Ej <= Ei and Ei - Si > Ej - Sj, we say that cowi is stronger than cowj.
For each cow, how many cows are stronger than her? Farmer John needs your help!
Input
The input contains multiple test cases.
For each test case, the first line is an integer N (1 <= N <= 105), which is the number of cows. Then come N lines, the i-th of which contains two integers: S and E(0 <= S < E <= 105) specifying the start end location respectively of a range preferred by some cow. Locations are given as distance from the start of the ridge.
The end of the input contains a single 0.
Output
For each test case, output one line containing n space-separated integers, the i-th of which specifying the number of cows that are stronger than cowi.
Sample Input
3
1 2
0 3
3 4
0
Sample Output
1 0 0
Description:
有n頭牛,每頭牛對應一個區間 [Si,Ei],如果牛j 的區間是牛 i 的區間的真子集( j 區間小於 i 區間且不重合),那麼就說牛i 比牛j 強壯,計算每頭牛有多少頭牛比他強壯
Solution:
首先對區間進行排序,排序規則為:按區間的右端點從大到小排序,如果右端點相同,則左端點小的排在前面
那麼當讀取到第 i 個牛的 Si 和 Ei時,之前(假設任意兩個區間不會完全相同)的牛的 Sj(j<=i-1) <= Si 的這些牛就都比 i 號牛強壯了。列舉區間,不斷插入區間左端點,因為區間右端點是保持遞減的,所以對於某個區間(Si, Ei),只需要查詢樹狀陣列中 [1, Si] 這一段有多少已經插入的資料,就能知道有多少個區間是比它大的,這裡需要注意的是多個區間相等的情況,因為有排序,所以它們在排序後的陣列中一定是相鄰的,所以在遇到有相等區間的情況時,當前的區間的答案就等於上一個相等的區間的答案。
由於樹狀陣列不能含有0元,需要對每個區間的左右端點進行加1.
Code:
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <map>
#define Fio ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define fopen freopen("in.txt", "r", stdin); freopen("out.txt", "w", stdout);
#define mst(a, b) memset(a, b, sizeof(a))
#define _rush() int T; cin >> T; while(T--)
#define rush() int T; scanf("%d", &T); while(T--)
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
const int INF = 0x3f3f3f3f;
const double eps = 1e-9;
const int Mod = 1e9 + 7;
const int MaxN = 1e5 + 5;
struct node {
int s, e, id;
}a[MaxN];
int presum[MaxN], ans[MaxN];
int n;
bool cmp(node x, node y) {
if(x.e == y.e) return x.s < y.s;
return x.e > y.e;
}
int lowbit(int x) { return x & (-x); }
void add(int p, int x) {
for(int i = p; i <= n; i += lowbit(i)) presum[i] += x;
}
int sum(int p) {
int ans = 0;
for(int i = p; i > 0; i -= lowbit(i)) ans += presum[i];
return ans;
}
int main()
{
//Fio;
while(scanf("%d", &n) != EOF) {
if(n == 0) return 0;
mst(presum, 0);
for(int i = 1; i <= n; i++) {
int s, e; scanf("%d %d", &s, &e);
a[i].s = s + 1, a[i].e = e + 1;
a[i].id = i;
}
sort(a + 1, a + 1 + n, cmp);
for(int i = 1; i <= n; i++) {
if(i != 1 && a[i].s == a[i-1].s && a[i].e == a[i-1].e) ans[a[i].id] = ans[a[i-1].id];
else ans[a[i].id] = sum(a[i].s);
add(a[i].s, 1);
}
for(int i = 1; i <= n; i++)
cout << ans[i] << " ";
cout << endl;
}
return 0;
}