1. 程式人生 > >bzoj2648

bzoj2648

優化 += 遞歸 ans insert sed oid zoj include

http://www.lydsy.com/JudgeOnline/problem.php?id=2648

kdtree裸題。。。

抄板子一邊抄對了。。。

挺好理解的,就是說我們先找出中間的元素,然後小的放左邊,大的放右邊,這樣我們就確定了這個點,然後維度換一下,遞歸建樹,很像splay,其實就是把平面每次一分為二,先橫著再豎著。。。

然後那個get挺神奇的,大概就是估計一下現在這個點距離下一個區域的距離?其實就是優化枚舉,減少了很多重復狀態。。。

技術分享
#include<bits/stdc++.h>
using namespace std;
const int N = 1000010, inf = 1 << 29
; struct data { int l, r, d[2], min[2], max[2]; } t[N]; int n, m, root, ans, d; bool cp(data x, data y) { if(x.d[d] != y.d[d]) return x.d[d] < y.d[d]; return x.d[d ^ 1] < y.d[d ^ 1]; } void update(int k) { for(int i = 0; i < 2; ++i) { if(t[k].l) t[k].min[i] = min(t[k].min[i], t[t[k].l].min[i]), t[k].max[i] = max(t[k].max[i], t[t[k].l].max[i]);
if(t[k].r) t[k].min[i] = min(t[k].min[i], t[t[k].r].min[i]), t[k].max[i] = max(t[k].max[i], t[t[k].r].max[i]); } } int get(int k, data x) { int ret = 0; for(int i = 0; i < 2; ++i) ret += max(t[k].min[i] - x.d[i], 0) + max(x.d[i] - t[k].max[i], 0); return ret; } int build(int l, int r, int
now) { d = now; int mid = (l + r) >> 1; nth_element(t + l + 1, t + mid + 1, t + r + 1, cp); for(int i = 0; i < 2; ++i) t[mid].min[i] = t[mid].max[i] = t[mid].d[i]; if(l < mid) t[mid].l = build(l, mid - 1, now ^ 1); if(r > mid) t[mid].r = build(mid + 1, r, now ^ 1); update(mid); return mid; } void insert(int k, int now, data x) { if(x.d[now] < t[k].d[now]) { if(t[k].l) insert(t[k].l, now ^ 1, x); else { t[k].l = ++n; for(int i = 0; i < 2; ++i) t[n].max[i] = t[n].min[i] = t[n].d[i] = x.d[i]; } } else { if(t[k].r) insert(t[k].r, now ^ 1, x); else { t[k].r = ++n; for(int i = 0; i < 2; ++i) t[n].max[i] = t[n].min[i] = t[n].d[i] = x.d[i]; } } update(k); } void query(int k, int now, data x) { int d = abs(t[k].d[0] - x.d[0]) + abs(t[k].d[1] - x.d[1]), dl = inf, dr = inf; ans = min(ans, d); if(t[k].l) dl = get(t[k].l, x); if(t[k].r) dr = get(t[k].r, x); if(dl < dr) { if(dl < ans) query(t[k].l, now ^ 1, x); if(dr < ans) query(t[k].r, now ^ 1, x); } else { if(dr < ans) query(t[k].r, now ^ 1, x); if(dl < ans) query(t[k].l, now ^ 1, x); } } int main() { scanf("%d%d", &n, &m); for(int i = 1; i <= n; ++i) scanf("%d%d", &t[i].d[0], &t[i].d[1]); root = build(1, n, 0); while(m--) { int opt; data x; scanf("%d%d%d", &opt, &x.d[0], &x.d[1]); if(opt == 1) insert(root, 0, x); if(opt == 2) { ans = inf; query(root, 0, x); printf("%d\n", ans); } } return 0; }
View Code

bzoj2648