HihoCoder - 1421(四叉树,模板)

模板说明:

提供传入vector的构造函数,可高效查询圆形区域的点列表。每块叶子区域点数限制为总数的根号级别。

代码:

// HihoCoder - 1421
//Quadtree 叫四叉树,看起来类似于区域线段树

#include <iostream>
#include <vector>
#include <algorithm>
#include <stdio.h>

using namespace std;
struct node {
	vector<pair<int, int>>p; //节点序列
	node *ul, *ur, *dl, *dr;
	pair<int, int> range_x, range_y;
	node() {
		p.clear();
		ul = ur = dl = dr = NULL;
	}
	void print() {
		cout << "inrange: x:[" << range_x.first << "," << range_x.second << "]";
		cout << ", y:[" << range_y.first << "," << range_y.second << "]" << endl;
		cout << "Point list: " << endl;
		for (int i = 0; i < p.size(); i++) {
			cout << "(" << p[i].first << "," << p[i].second << ") ";
		}
		cout << endl;
	}
};
class Quadtree
{
public:
	Quadtree();
	Quadtree(const vector<pair<int, int>>&p);
	Quadtree(const vector<pair<int, int>>&p, int set_limit);
	~Quadtree();
	vector<pair<int, int>> getPointList(pair<int, int>o, int r);

private:
	int limit;
	node* root;
	void split(node* x);
	void add(pair<int, int>point);
	void del(node* rt);
	void push(node* root, const vector<pair<int, int>>& p, pair<int, int>range_x, pair<int, int>range_y);
	bool is_InRange(int pos, pair<int, int>range);
	bool is_InRange(pair<int, int>point, pair<int, int>o, int r);
	bool is_InRange(node* rt, pair<int, int>o, int r);
	void getPointList(node* rt, pair<int, int>o, int r, vector<pair<int, int>>& ans);
};
Quadtree::Quadtree() {
	limit = 10;
	root = new node;
}
Quadtree::Quadtree(const vector<pair<int, int>>& p) {
	root = new node;
	limit = (int)pow(p.size(), 1.0 / 2) + 1; // 根号下点数
	pair<int, int> range_x, range_y;
	if (p.size() > 0) {
		range_x.first = range_x.second = p[0].first;
		range_y.first = range_y.second = p[0].second;
	}
	for (int i = 0; i < p.size(); i++) {
		range_x.first = min(range_x.first, p[i].first);
		range_x.second = max(range_x.second, p[i].first);
		range_y.first = min(range_y.first, p[i].second);
		range_y.second = max(range_y.second, p[i].second);
	}
	push(root, p, range_x, range_y);
	split(root);
}
Quadtree::Quadtree(const vector<pair<int, int>>& p, int set_limit) {
	root = new node;
	limit = set_limit;
	pair<int, int> range_x, range_y;
	if (p.size() > 0) {
		range_x.first = range_x.second = p[0].first;
		range_y.first = range_y.second = p[0].second;
	}
	for (int i = 0; i < p.size(); i++) {
		range_x.first = min(range_x.first, p[i].first);
		range_x.second = max(range_x.second, p[i].first);
		range_y.first = min(range_y.first, p[i].second);
		range_y.second = max(range_y.second, p[i].second);
	}
	push(root, p, range_x, range_y);
	split(root);
}
Quadtree::~Quadtree() {
	del(root);
}
inline bool Quadtree::is_InRange(int pos, pair<int, int>range) {
	return pos >= range.first && pos <= range.second;
}
inline bool Quadtree::is_InRange(pair<int, int>point, pair<int, int>o, int r) {
	long long int disx = point.first - o.first, disy = point.second - o.second;
	return disx * disx + disy * disy <= r * r;
}
inline bool Quadtree::is_InRange(node* rt, pair<int, int>o, int r) {
	return is_InRange(make_pair(rt->range_x.first, rt->range_y.first), o, r)
		&& is_InRange(make_pair(rt->range_x.first, rt->range_y.second), o, r)
		&& is_InRange(make_pair(rt->range_x.second, rt->range_y.first), o, r)
		&& is_InRange(make_pair(rt->range_x.second, rt->range_y.second), o, r);
}
void Quadtree::del(node* rt) {
	if (rt->dl != NULL) del(rt->dl);
	if (rt->dr != NULL) del(rt->dr);
	if (rt->ul != NULL) del(rt->ul);
	if (rt->ur != NULL) del(rt->ur);
	delete rt;
}
void Quadtree::split(node* rt) { 
	int mid_x = (rt->range_x.first + rt->range_x.second) / 2;
	int mid_y = (rt->range_y.first + rt->range_y.second) / 2;
	rt->ul = new node, rt->ur = new node, rt->dl = new node, rt->dr = new node;
	// ul
	push(rt->ul, rt->p, make_pair(rt->range_x.first, mid_x), make_pair(mid_y + 1, rt->range_y.second));
	if (rt->ul->p.size() == 0) {
		del(rt->ul);
		rt->ul = NULL;
	}	
	else if (rt->ul->p.size() > limit) {
		split(rt->ul);
	}
	// ur 
	push(rt->ur, rt->p, make_pair(mid_x + 1, rt->range_x.second), make_pair(mid_y + 1, rt->range_y.second));
	if (rt->ur->p.size() == 0) {
		del(rt->ur);
		rt->ur = NULL;
	}
	else if (rt->ur->p.size() > limit) {
		split(rt->ur);
	}
	// dl
	push(rt->dl, rt->p, make_pair(rt->range_x.first, mid_x), make_pair(rt->range_y.first, mid_y));
	if (rt->dl->p.size() == 0) {
		del(rt->dl);
		rt->dl = NULL;
	}
	else if (rt->dl->p.size() > limit) {
		split(rt->dl);
	}
	// dr
	push(rt->dr, rt->p, make_pair(mid_x + 1, rt->range_x.second), make_pair(rt->range_y.first, mid_y));
	if (rt->dr->p.size() == 0) {
		del(rt->dr);
		rt->dr = NULL;
	}
	else if (rt->dr->p.size() > limit) {
		split(rt->dr);
	}
}
void Quadtree::push(node *rt, const vector<pair<int, int>>& p, pair<int, int>range_x, pair<int, int>range_y) {
	for (int i = 0; i < p.size(); i++) {
		if (is_InRange(p[i].first, range_x) && is_InRange(p[i].second, range_y))
			rt->p.push_back(p[i]);
	}
	rt->range_x = range_x;
	rt->range_y = range_y;
}
void Quadtree::getPointList(node* rt, pair<int, int>o, int r, vector<pair<int, int>>& ans) {
	if (is_InRange(rt, o, r) == true) {
		for (int i = 0; i < rt->p.size(); i++) {
			ans.push_back(rt->p[i]);
		}
		return ;
	}
	if (rt->p.size() <= limit) {
		for (int i = 0; i < rt->p.size(); i++) {
			if (is_InRange(rt->p[i], o, r) == true) {
				ans.push_back(rt->p[i]);
			}
		}
		return;
	}
	if (rt->dl != NULL) {
		getPointList(rt->dl, o, r, ans);
	}
	if (rt->dr != NULL) {
		getPointList(rt->dr, o, r, ans);
	}
	if (rt->ul != NULL) {
		getPointList(rt->ul, o, r, ans);
	}
	if (rt->ur != NULL) {
		getPointList(rt->ur, o, r, ans);
	}
}
vector<pair<int, int>> Quadtree::getPointList(pair<int, int>o, int r) {
	vector<pair<int, int>>ret;
	getPointList(root, o, r, ret);
	return ret;
} 
void Quadtree::add(pair<int, int>point) { 

} // not ok

int main()
{
	ios::sync_with_stdio(false);
	int n, m;
	cin >> n >> m;
	vector<pair<int, int>>p;
	for (int i = 0; i < n;  i++) {
		int temp_x, temp_y;
		cin >> temp_x >> temp_y;
		p.push_back(make_pair(temp_x, temp_y));
	}
	Quadtree ans = Quadtree(p);
	while (m--) {
		pair<int, int>o;
		int r;
		cin >> o.first >> o.second >> r;
		printf("%d\n", ans.getPointList(o, r).size());
	}
}


发布了227 篇原创文章 · 获赞 142 · 访问量 9万+

猜你喜欢

转载自blog.csdn.net/qq_36306833/article/details/102875201
今日推荐