【JAVA】Cows(POJ 2481)(IndexTree)

【JAVA】Cows(POJ 2481)(IndexTree)

题目地址: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();
		}
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值