對於 維的點,用 維護
每一維交替劃分
注意暴力的剪枝
參考博客:[學習筆記] kd-tree
例題一:P4169 [Violet]天使玩偶/SJY擺棋子
多次操作,支持查詢曼哈頓距離最近的點 與 插入一個點
這題要開 優化
#include<bits/stdc++.h>
#define rint register int
#define deb(x) cerr<<#x<<" = "<<(x)<<'\n';
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int maxn = 2e6 + 5;
const double alpha = 0.75;
int n, m, rt, tot, now, ans;
int sta[maxn], top;
struct node{
int pla[2];
} a[maxn];
struct tree{
int mx[2], mn[2], sz, ls, rs;
node place;
} t[maxn];
inline int New(){
if(top) return sta[top--];
return ++tot;
}
inline bool cmp(const node &A, const node &B){
return A.pla[now] < B.pla[now];
}
inline void update(int p){
for(int i=0; i<=1; i++){
t[p].mx[i] = t[p].mn[i] = t[p].place.pla[i];
if(t[p].ls) t[p].mx[i] = max(t[p].mx[i], t[t[p].ls].mx[i]), \
t[p].mn[i] = min(t[p].mn[i], t[t[p].ls].mn[i]);
if(t[p].rs) t[p].mx[i] = max(t[p].mx[i], t[t[p].rs].mx[i]), \
t[p].mn[i] = min(t[p].mn[i], t[t[p].rs].mn[i]);
}
t[p].sz = t[t[p].ls].sz + t[t[p].rs].sz + 1;
}
inline int build(int l, int r, int opt){
if(l > r) return 0;
int x = New(), mid = l + r >> 1; now = opt;
nth_element(a+l, a+mid, a+r+1, cmp); t[x].place = a[mid];
t[x].ls = build(l, mid-1, opt^1);
t[x].rs = build(mid+1, r, opt^1);
update(x); return x;
}
inline void pia(int p, int cnt){
if(t[p].ls) pia(t[p].ls, cnt);
a[cnt+t[t[p].ls].sz+1] = t[p].place, sta[++top] = p;
if(t[p].rs) pia(t[p].rs, cnt+t[t[p].ls].sz+1);
}
inline void check(int &p, int opt){
if(t[p].sz*alpha<t[t[p].ls].sz || t[p].sz*alpha<t[t[p].rs].sz)
pia(p, 0), p = build(1, t[p].sz, opt);
}
inline void insert(node ret, int &p, int opt){
if(!p){
p = New(); t[p].place = ret;
t[p].ls = t[p].rs = 0;
update(p); return;
}
if(ret.pla[opt] <= t[p].place.pla[opt]) insert(ret, t[p].ls, opt^1);
else insert(ret, t[p].rs, opt^1);
update(p); check(p, opt);
}
inline int getdis(node a, int p){
int ret = 0;
for(int i=0; i<=1; i++)
ret += max(0, a.pla[i]-t[p].mx[i]) + max(0, t[p].mn[i]-a.pla[i]);
return ret;
}
inline int dis(node a, node b){
return abs(a.pla[0]-b.pla[0]) + abs(a.pla[1]-b.pla[1]);
}
inline void query(node ret, int p){
ans = min(ans, dis(ret, t[p].place));
int tmpl = inf, tmpr = inf;
if(t[p].ls) tmpl = getdis(ret, t[p].ls);
if(t[p].rs) tmpr = getdis(ret, t[p].rs);
if(tmpl < tmpr){
if(tmpl < ans) query(ret, t[p].ls);
if(tmpr < ans) query(ret, t[p].rs);
} else {
if(tmpr < ans) query(ret, t[p].rs);
if(tmpl < ans) query(ret, t[p].ls);
}
}
int main() {
scanf("%d%d", &n, &m);
for(int i=1; i<=n; i++) scanf("%d%d", &a[i].pla[0], &a[i].pla[1]);
rt = build(1, n, 0);
for(int i=1; i<=m; i++){
int opt; node ret;
scanf("%d%d%d", &opt, &ret.pla[0], &ret.pla[1]);
if(opt == 1) insert(ret, rt, 0);
else ans = inf, query(ret, rt), printf("%d\n", ans);
}
}
例題二:[Sdoi2010]Hide and Seek
查詢一個點的曼哈頓距離最大與最小的差值,的最小值
#include<bits/stdc++.h>
#define rint register int
#define deb(x) cerr<<#x<<" = "<<(x)<<'\n';
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int maxn = 2e6 + 5;
const double alpha = 0.75;
int n, m, rt, tot, now, ans;
int sta[maxn], top;
struct node{
int pla[2];
} a[maxn];
struct tree{
int mx[2], mn[2], sz, ls, rs;
node place;
} t[maxn];
inline int New(){
if(top) return sta[top--];
return ++tot;
}
inline bool cmp(const node &A, const node &B){
return A.pla[now] < B.pla[now];
}
inline void update(int p){
for(int i=0; i<=1; i++){
t[p].mx[i] = t[p].mn[i] = t[p].place.pla[i];
if(t[p].ls) t[p].mx[i] = max(t[p].mx[i], t[t[p].ls].mx[i]), \
t[p].mn[i] = min(t[p].mn[i], t[t[p].ls].mn[i]);
if(t[p].rs) t[p].mx[i] = max(t[p].mx[i], t[t[p].rs].mx[i]), \
t[p].mn[i] = min(t[p].mn[i], t[t[p].rs].mn[i]);
}
t[p].sz = t[t[p].ls].sz + t[t[p].rs].sz + 1;
}
inline int build(int l, int r, int opt){
if(l > r) return 0;
int x = New(), mid = l + r >> 1; now = opt;
nth_element(a+l, a+mid, a+r+1, cmp); t[x].place = a[mid];
t[x].ls = build(l, mid-1, opt^1);
t[x].rs = build(mid+1, r, opt^1);
update(x); return x;
}
inline void pia(int p, int cnt){
if(t[p].ls) pia(t[p].ls, cnt);
a[cnt+t[t[p].ls].sz+1] = t[p].place, sta[++top] = p;
if(t[p].rs) pia(t[p].rs, cnt+t[t[p].ls].sz+1);
}
inline void check(int &p, int opt){
if(t[p].sz*alpha<t[t[p].ls].sz || t[p].sz*alpha<t[t[p].rs].sz)
pia(p, 0), p = build(1, t[p].sz, opt);
}
inline void insert(node ret, int &p, int opt){
if(!p){
p = New(); t[p].place = ret;
t[p].ls = t[p].rs = 0;
update(p); return;
}
if(ret.pla[opt] <= t[p].place.pla[opt]) insert(ret, t[p].ls, opt^1);
else insert(ret, t[p].rs, opt^1);
update(p); check(p, opt);
}
inline int getdis1(node a, int p){
int ret = 0;
for(int i=0; i<=1; i++)
ret += max(0, a.pla[i]-t[p].mx[i]) + max(0, t[p].mn[i]-a.pla[i]);
return ret;
}
inline int getdis2(node a, int p){
int ret = 0;
for(int i=0; i<=1; i++)
ret += max(abs(a.pla[i]-t[p].mx[i]), abs(t[p].mn[i]-a.pla[i]));
return ret;
}
inline int dis(node a, node b){
return abs(a.pla[0]-b.pla[0]) + abs(a.pla[1]-b.pla[1]);
}
inline void query1(node ret, int p){
if(dis(ret, t[p].place))
ans = min(ans, dis(ret, t[p].place));
int tmpl = inf, tmpr = inf;
if(t[p].ls) tmpl = getdis1(ret, t[p].ls);
if(t[p].rs) tmpr = getdis1(ret, t[p].rs);
if(tmpl < tmpr){
if(tmpl < ans) query1(ret, t[p].ls);
if(tmpr < ans) query1(ret, t[p].rs);
} else {
if(tmpr < ans) query1(ret, t[p].rs);
if(tmpl < ans) query1(ret, t[p].ls);
}
}
inline void query2(node ret, int p){
ans = max(ans, dis(ret, t[p].place));
int tmpl = -inf, tmpr = -inf;
if(t[p].ls) tmpl = getdis2(ret, t[p].ls);
if(t[p].rs) tmpr = getdis2(ret, t[p].rs);
if(tmpl > tmpr){
if(tmpl > ans) query2(ret, t[p].ls);
if(tmpr > ans) query2(ret, t[p].rs);
} else {
if(tmpr > ans) query2(ret, t[p].rs);
if(tmpl > ans) query2(ret, t[p].ls);
}
}
int main() {
scanf("%d", &n);
for(int i=1; i<=n; i++) scanf("%d%d", &a[i].pla[0], &a[i].pla[1]);
rt = build(1, n, 0);
int res = inf, mn, mx;
for(int i=1; i<=n; i++){
ans = inf;
query1(a[i], rt), mn = ans;
ans = -inf;
query2(a[i], rt), mx = ans;
res = min(res, mx - mn);
}
printf("%d\n", res);
}
例題三:P2093 [國家集訓隊]JZPFAR
歐式距離第 遠,維護一個大小爲 的堆
#include<bits/stdc++.h>
#define rint register int
#define deb(x) cerr<<#x<<" = "<<(x)<<'\n';
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int maxn = 2e6 + 5;
const double alpha = 0.75;
int n, m, rt, tot, now;
int sta[maxn], top;
struct node{
int pla[2], id;
} a[maxn];
struct tree{
int mx[2], mn[2], sz, ls, rs, id;
node place;
} t[maxn];
struct Node{
ll dis; int id;
bool operator < (Node A) const {
return dis == A.dis ? id < A.id : dis > A.dis;
}
};
priority_queue <Node> q;
inline int New(){
if(top) return sta[top--];
return ++tot;
}
inline bool cmp(const node &A, const node &B){
return A.pla[now] < B.pla[now];
}
inline void update(int p){
for(int i=0; i<=1; i++){
t[p].mx[i] = t[p].mn[i] = t[p].place.pla[i];
if(t[p].ls) t[p].mx[i] = max(t[p].mx[i], t[t[p].ls].mx[i]), \
t[p].mn[i] = min(t[p].mn[i], t[t[p].ls].mn[i]);
if(t[p].rs) t[p].mx[i] = max(t[p].mx[i], t[t[p].rs].mx[i]), \
t[p].mn[i] = min(t[p].mn[i], t[t[p].rs].mn[i]);
}
t[p].sz = t[t[p].ls].sz + t[t[p].rs].sz + 1;
}
inline int build(int l, int r, int opt){
if(l > r) return 0;
int x = New(), mid = l + r >> 1; now = opt;
nth_element(a+l, a+mid, a+r+1, cmp);
t[x].place = a[mid], t[x].id = a[mid].id;
t[x].ls = build(l, mid-1, opt^1);
t[x].rs = build(mid+1, r, opt^1);
update(x); return x;
}
inline void pia(int p, int cnt){
if(t[p].ls) pia(t[p].ls, cnt);
a[cnt+t[t[p].ls].sz+1] = t[p].place, sta[++top] = p;
if(t[p].rs) pia(t[p].rs, cnt+t[t[p].ls].sz+1);
}
inline void check(int &p, int opt){
if(t[p].sz*alpha<t[t[p].ls].sz || t[p].sz*alpha<t[t[p].rs].sz)
pia(p, 0), p = build(1, t[p].sz, opt);
}
inline void insert(node ret, int &p, int opt){
if(!p){
p = New(); t[p].place = ret;
t[p].ls = t[p].rs = 0;
update(p); return;
}
if(ret.pla[opt] <= t[p].place.pla[opt]) insert(ret, t[p].ls, opt^1);
else insert(ret, t[p].rs, opt^1);
update(p); check(p, opt);
}
inline ll pow2(ll x){ return x * x; }
inline ll getdis(node a, int p){
ll ret = 0;
for(int i=0; i<=1; i++)
ret += max(pow2(a.pla[i]-t[p].mx[i]), pow2(t[p].mn[i]-a.pla[i]));
return ret;
}
inline ll dis(node a, node b){
return pow2(a.pla[0]-b.pla[0]) + pow2(a.pla[1]-b.pla[1]);
}
inline void query(node ret, int p){
ll dist = dis(ret, t[p].place);
ll tmpl = -inf, tmpr = -inf;
if(t[p].ls) tmpl = getdis(ret, t[p].ls);
if(t[p].rs) tmpr = getdis(ret, t[p].rs);
if(dist>q.top().dis || (dist==q.top().dis && t[p].id<q.top().id)){
q.pop();
q.push({dist, t[p].id});
}
if(tmpl > tmpr){
if(tmpl >= q.top().dis) query(ret, t[p].ls);
if(tmpr >= q.top().dis) query(ret, t[p].rs);
} else {
if(tmpr >= q.top().dis) query(ret, t[p].rs);
if(tmpl >= q.top().dis) query(ret, t[p].ls);
}
}
int main() {
scanf("%d", &n);
for(int i=1; i<=n; i++) scanf("%d%d", &a[i].pla[0], &a[i].pla[1]), a[i].id = i;
rt = build(1, n, 0);
scanf("%d", &m);
for(int i=1; i<=m; i++){
int k; node ret;
scanf("%d%d%d", &ret.pla[0], &ret.pla[1], &k);
while(q.size()) q.pop();
for(int i=1; i<=k; i++) q.push({-1, 0});
query(ret, rt);
printf("%d\n", q.top().id);
}
}
例題四:[Cqoi2016]K遠點對
歐氏距離下的第 遠點對, 維護一個大小爲 的堆
#include<bits/stdc++.h>
#define rint register int
#define deb(x) cerr<<#x<<" = "<<(x)<<'\n';
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int maxn = 2e6 + 5;
const double alpha = 0.75;
int n, m, rt, tot, now;
int sta[maxn], top;
struct node{
int pla[2], id;
} a[maxn];
struct tree{
int mx[2], mn[2], sz, ls, rs;
node place;
} t[maxn];
struct Node{
ll dis;
bool operator < (Node A) const {
return dis > A.dis;
}
};
priority_queue <Node> q;
inline int New(){
if(top) return sta[top--];
return ++tot;
}
inline bool cmp(const node &A, const node &B){
return A.pla[now] < B.pla[now];
}
inline void update(int p){
for(int i=0; i<=1; i++){
t[p].mx[i] = t[p].mn[i] = t[p].place.pla[i];
if(t[p].ls) t[p].mx[i] = max(t[p].mx[i], t[t[p].ls].mx[i]), \
t[p].mn[i] = min(t[p].mn[i], t[t[p].ls].mn[i]);
if(t[p].rs) t[p].mx[i] = max(t[p].mx[i], t[t[p].rs].mx[i]), \
t[p].mn[i] = min(t[p].mn[i], t[t[p].rs].mn[i]);
}
t[p].sz = t[t[p].ls].sz + t[t[p].rs].sz + 1;
}
inline int build(int l, int r, int opt){
if(l > r) return 0;
int x = New(), mid = l + r >> 1; now = opt;
nth_element(a+l, a+mid, a+r+1, cmp); t[x].place = a[mid];
t[x].ls = build(l, mid-1, opt^1);
t[x].rs = build(mid+1, r, opt^1);
update(x); return x;
}
inline void pia(int p, int cnt){
if(t[p].ls) pia(t[p].ls, cnt);
a[cnt+t[t[p].ls].sz+1] = t[p].place, sta[++top] = p;
if(t[p].rs) pia(t[p].rs, cnt+t[t[p].ls].sz+1);
}
inline void check(int &p, int opt){
if(t[p].sz*alpha<t[t[p].ls].sz || t[p].sz*alpha<t[t[p].rs].sz)
pia(p, 0), p = build(1, t[p].sz, opt);
}
inline void insert(node ret, int &p, int opt){
if(!p){
p = New(); t[p].place = ret;
t[p].ls = t[p].rs = 0;
update(p); return;
}
if(ret.pla[opt] <= t[p].place.pla[opt]) insert(ret, t[p].ls, opt^1);
else insert(ret, t[p].rs, opt^1);
update(p); check(p, opt);
}
inline ll pow2(ll x){ return x * x; }
inline ll getdis(node a, int p){
ll ret = 0;
for(int i=0; i<=1; i++)
ret += max(pow2(a.pla[i]-t[p].mx[i]), pow2(t[p].mn[i]-a.pla[i]));
return ret;
}
inline ll dis(node a, node b){
return pow2(a.pla[0]-b.pla[0]) + pow2(a.pla[1]-b.pla[1]);
}
inline void query(node ret, int p){
ll dist = dis(ret, t[p].place);
ll tmpl = -inf, tmpr = -inf;
if(t[p].ls) tmpl = getdis(ret, t[p].ls);
if(t[p].rs) tmpr = getdis(ret, t[p].rs);
if(dist>q.top().dis){
q.pop();
q.push({dist});
}
if(tmpl > tmpr){
if(tmpl >= q.top().dis) query(ret, t[p].ls);
if(tmpr >= q.top().dis) query(ret, t[p].rs);
} else {
if(tmpr >= q.top().dis) query(ret, t[p].rs);
if(tmpl >= q.top().dis) query(ret, t[p].ls);
}
}
int main() {
scanf("%d%d", &n, &m); m <<= 1;
for(int i=1; i<=n; i++) scanf("%d%d", &a[i].pla[0], &a[i].pla[1]);
rt = build(1, n, 0);
for(int i=1; i<=m; i++) q.push({-1});
for(int i=1; i<=n; i++){
node ret = a[i];
query(ret, rt);
}
printf("%lld\n", q.top().dis);
}