POJ-2352 Tree Array + Thinking

The main idea of ​​the topic: Given n pairs of x and y coordinates, find the number of points at different levels [0, n-1]. The level of each point depends on: the number of points below and to the left of the point.

Idea: Use a tree array to maintain the number of stars in different intervals; sort the input coordinate pairs according to y, and sort the same y according to x (ascending order). In this way, you can directly use the tree array to maintain the number of stars in [1,x], because each time the level of a new point added to the tree array must be greater than or equal to the level of the previous point . The coordinates given in the title may be 0, so the x coordinate is processed as +1 .

The thinking of using the ANS array: Use the ANS array to save the number of points of each level. First obtain the level of the point i added to the tree array, and then increment the elements of the ANS array with the level as the subscript; then add 1 to the number of stars in the interval [1,x] of the tree array to update.

Be sure to pay attention to the order of level and interval update, because in this question, the level of the point does not include itself, so you need to find the level first and then increase it.

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;

const int maxn = 15005;
int n, msum[maxn << 2], x, y, ANS[maxn];
struct Node{
	int x, y;
}node[maxn];

bool cmp(Node a, Node b){
	if(a.y == b.y) return a.x < b.x;
	return a.y < b.y;
}

void update(int x, int v){
	//要更新维护区间内的所有地方 ,因为,题目中给的x坐标并不知规定小于n。所以加lowbit 一直到maxn << 2. 
	for(int i = x; i <= maxn << 2;i += i & (-i)){	 
		msum[i] += v;
	}
}

int getNum(int x){
	int ans = 0;
	for(int i = x;i > 0; i -= i & (-i)){
		ans += msum[i];
	}
	return ans;
}

int main(){
	while(scanf("%d", &n) != EOF){
		memset(ANS, 0, sizeof ANS);
		memset(node, 0, sizeof node);
		for(int i = 1;i <= n;i++){
			scanf("%d%d", &node[i].x, &node[i].y);
			node[i].x++;//该题需要防止下标为0; 
		}
		sort(node + 1, node + n + 1, cmp);
		//依次加入树状数组进行维护
		for(int i = 1; i <= n;i++) {
			ANS[getNum(node[i].x)]++;//等级为getNum(node[i].x)的星星数+1 
			update(node[i].x, 1);//更新维护区间,星星数加1 
		}
		for(int i = 0;i < n;i++){
			printf("%d\n",ANS[i]);
		}
	}
	
	return 0;
}

 

Guess you like

Origin blog.csdn.net/qq_40596572/article/details/103997044