题目地址:http://poj.org/problem?id=2481
思路:
能量比当前牛大的牛,则吃草区间是大于当前牛的。
即:起始坐标小于等于当前牛的起始坐标且结束坐标大于等于当前牛的结束下标的牛的数量,减去和当前牛的吃草区间完全相等的牛的数量即可。
首先,要确保起始坐标小于等于当前牛的,则根据起始下标升序排序,就可以确保在处理当前牛时,已经被处理的牛的起始下标小于等于当前牛的起始下标。
其次,在已经被处理的牛中,寻找结束下标大于等于当前牛的结束下标的牛的数量P;
再次,对于吃草区间和当前牛完全相等的,排序时排在一起的话,就可以统计出来,在当前牛之前,已经被处理的牛中,坐标区间和自己完全相等的牛的数量Q;
则【P-Q】即为比当前牛能量大的牛的数量。
坐标取值范围为【0,10万】,则可以使用IndexTree,叶节点和坐标值对应。对于每头牛,查找大于等于吃草的结束坐标的牛的数量,再减去与自己的吃草区间完全相同的牛的数量,即可。
代码:
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.Comparator;
import java.util.StringTokenizer;
/*
7
5 6
2 3
1 8
2 16
4 7
2 5
1 3
0
3 4 0 0 2 2 1
*/
public class Main {
static int N;
static Node cow[];
static int[] tree, ans;
static class Node {
int idx, s, e;
public Node(int i, int start, int end) {
idx = i;
s = start;
e = end;
}
}
static int query(int start, int end) {
int ret = 0, s = start, e = end;
while (s <= e) {
if (s % 2 == 1)
ret += tree[s];
if (e % 2 == 0)
ret += tree[e];
s = (s + 1) / 2;
e = (e - 1) / 2;
}
return ret;
}
static void update(int n) {
while (n > 0) {
tree[n]++;
n /= 2;
}
}
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st;
while (true) {
N = Integer.parseInt(br.readLine());
if (N == 0)
break;
cow = new Node[N];
tree = new int[262144];
ans = new int[N];
for (int i = 0; i < N; i++) {
st = new StringTokenizer(br.readLine());
cow[i] = new Node(i, Integer.parseInt(st.nextToken()), Integer.parseInt(st.nextToken()));
}
Arrays.sort(cow, 0, N, new Comparator<Node>() {
@Override
public int compare(Node a, Node b) {
return a.s == b.s ? b.e - a.e : a.s - b.s; // 按起始点排序(起始点相同,则按终点排序)
}
});
int cnt = 0;
for (int i = 0; i < N; i++) {
if (i > 0 && cow[i - 1].s == cow[i].s && cow[i - 1].e == cow[i].e)
cnt++; // 起点和终点相同的牛有多少
else
cnt = 0;
ans[cow[i].idx] = query(131072 + cow[i].e, 262143) - cnt;// 到目前为止,终点>=当前牛的,起点<=当前牛的,有多少,再减去完全相等的,即为答案
update(131072 + cow[i].e);// 当前终点为子节点,以及其父节点,各节点加1
}
System.out.print(ans[0]);
for (int i = 1; i < N; i++)
System.out.print(" " + ans[i]);
System.out.println();
}
}
}