标签:int 中间 upd .com alt clu ++ amp min
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; }
标签:int 中间 upd .com alt clu ++ amp min
原文地址:http://www.cnblogs.com/19992147orz/p/6880695.html