模板说明:
提供传入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());
}
}