poj2481 cows树状数组

来源:http://gzhu-101majia.iteye.com/blog/1143065

题目大意:给你很多线段的头S和尾E,问每一条线段中包含了多少个线段,(S和E相同不计在内)。这题先一看,完全不知道什么方法,感觉非常的难办。

但是!树状数组可以轻松解决这个问题!!!首先,将她们线段的s和e当做是(s,e)一个点,这样子把所有点画出来,你就会发现一个很神奇的现象,题目要求就会变成:问每一个点的左上角有多少个点?

      !!!这样不就和那题最简单的stars一样吗???!!!

          stars那题是问左下角有多少个点,而这题是问左上角,而且点不是有序排好的,所以有些不同,特殊处理一下就可以。

       如果正常做,那个y是递增的,所以sum和update那个方向就会相反了,这个其实没什么所谓,一样的,排序的时候先y由大到小排,y相同时x由小到大排,这样小小的处理,就变成stars那题了!!!

       还有一点忘了,这题也是需要离散化的,离散化很重要很强大!!!

       就这样!走过路过不要错过!!!

#include <iostream>
#include <string.h>
#include <algorithm>
#include <stdio.h>
using namespace std;
#define N 100010
struct Node {
	int id;
	int first;
	int second;
};
Node pos[N];
int n;
int A[N];
int result[N];
int lowbit(int x) {
	return x & (-x);
}
void add(int x, int m) {
	while(x < N) {
		A[x] += m;
		x += lowbit(x);
	}
}

int sum(int end) {
	int result = 0;
	while(end > 0) {
		result += A[end];
		end -= lowbit(end);
	}
	return result;
}

bool cmp(Node l, Node r) {
	if (l.second != r.second) return l.second > r.second;
	else return l.first < r.first;
}

int main () {
	while(cin>>n && n != 0) {
		for (int i = 1; i <= n; i++) {
			scanf("%d %d", &pos[i].first, &pos[i].second);
			pos[i].id = i;
			pos[i].first += 1;
			pos[i].second += 1;
		}
		memset(A, 0, sizeof(A));
		memset(result, 0, sizeof(result));
		sort(pos+1, pos+n+1, cmp);

		result[pos[1].id] = sum(pos[1].first);
		add(pos[1].first, 1);
		for (int i = 2; i <= n; i++) {
			if (pos[i].first == pos[i-1].first &&
				pos[i].second == pos[i-1].second) {
				result[pos[i].id] = result[pos[i-1].id];
			}
			else 
				result[pos[i].id] = sum(pos[i].first);
			add(pos[i].first, 1);

		}
		/*
		for (int i = 1; i <= n; i++) {
			printf("%d ", A[i]);
		}
		printf("\n");
		*/
		for (int i = 1; i < n; i++) {
			printf("%d ", result[i]);
		}
		printf("%d\n", result[n]);
	}
	return 0;
}


你可能感兴趣的:(poj2481 cows树状数组)