BZOJ2648 SJY擺棋子(k-d樹)
阿新 • • 發佈:2018-12-14
題目連結 思路: 二維的樹,查詢的時候其實就是貪心搜尋+剪枝,樹的建樹和查詢網上很多,插入的時候就是暴力插入。可為啥我的暴力插入超時了,話說應該要像替罪羊樹那樣維護樹的平衡性吧。暴力重建+弱剪枝還超時了。
#include<bits/stdc++.h> #define endl "\n" typedef long long ll; const int maxn = 1e6 + 100; const int INF = 1e9 + 10; const double alpha = 0.75; using namespace std; const int MAX = 100000; char buf[MAX], *ps = buf, *pe = buf + 1; inline void rnext() { if(++ps == pe) pe = (ps = buf) + fread(buf, sizeof(char), sizeof(buf) / sizeof(char), stdin); } template <class T> inline bool in(T &ans) { ans = 0; T f = 1; if(ps == pe) return false;//EOF do{ rnext(); if('-' == *ps) f = -1; } while(!isdigit(*ps) && ps != pe); if(ps == pe) return false;//EOF do { ans = (ans<<1)+(ans<<3)+*ps-48; rnext(); } while(isdigit(*ps) && ps != pe); ans *= f; return true; } char bufout[MAX], outtmp[50],*pout = bufout, *pend = bufout + MAX; inline void write() { fwrite(bufout, sizeof(char), pout - bufout, stdout); pout = bufout; } inline void out_char(char c) { *(pout++) = c; if(pout == pend) write(); } inline void out_str(char *s) { while(*s) { *(pout++) = *(s++); if(pout == pend) write(); } } template <class T> inline void out_int(T x) { if(!x) { out_char('0'); return; } if(x < 0) x = -x,out_char('-'); int len = 0; while(x) { outtmp[len++] = x%10+48; x /= 10; } outtmp[len] = 0; for(int i = 0, j = len - 1; i < j; i++,j--) swap(outtmp[i],outtmp[j]); out_str(outtmp); } struct point { int data[2], split; point(int x = 0, int y = 0) { data[0] = x; data[1] = y; } void input() { in(data[0]); in(data[1]); } bool operator < (point p) const { if(data[split] != p.data[split]) return data[split] < p.data[split]; else return data[split ^ 1] < p.data[split ^ 1]; } } p[maxn]; struct kd_tree { int son[2], size; int mn[2], mx[2]; point p; } kd[maxn]; int n, m, T, kase = 1, stk[maxn], cnt; inline void update(int o) { kd[o].size = kd[kd[o].son[0]].size + kd[kd[o].son[1]].size + 1; for(int i = 0; i < 2; i++) { kd[o].mn[i] = min(kd[o].mn[i], kd[kd[o].son[0]].mn[i]); kd[o].mx[i] = max(kd[o].mx[i], kd[kd[o].son[0]].mx[i]); kd[o].mn[i] = min(kd[o].mn[i], kd[kd[o].son[1]].mn[i]); kd[o].mx[i] = max(kd[o].mx[i], kd[kd[o].son[1]].mx[i]); } } inline bool need_build(int o) { if(kd[o].size * alpha <= kd[kd[o].son[0]].size) return true; if(kd[o].size * alpha <= kd[kd[o].son[1]].size) return true; return false; } void dfs(int o, int &tot) { if(!o) return ; p[tot++] = kd[o].p; stk[cnt++] = o; dfs(kd[o].son[0], tot); dfs(kd[o].son[1], tot); } inline void create_node(int &o, point now, int sp) { o = stk[--cnt]; kd[o].son[0] = kd[o].son[1] = 0; for(int i = 0; i < 2; i++) kd[o].mn[i] = kd[o].mx[i] = now.data[i]; kd[o].p = now; kd[o].size = 1; kd[o].p.split = sp; } void build(int &o, int l, int r, int sp) { for(int i = l; i <= r; i++) p[i].split = sp; int mid = (l + r) >> 1; nth_element(p + l, p + mid, p + r + 1); create_node(o, p[mid], sp); if(l <= mid - 1) build(kd[o].son[0], l, mid - 1, 1 ^ sp); if(mid + 1 <= r) build(kd[o].son[1], mid + 1, r, 1 ^ sp); update(o); } inline int get_dis(point p1, point p2) { return abs(p1.data[0] - p2.data[0]) + abs(p1.data[1] - p2.data[1]); } inline bool enter(int o, int ans, point now, int now_dis, int sp) { if(!o) return false; for(int i = 0; i < 2; i++) { int da = now.data[i], flag = 0; if(i != sp) flag = now_dis; if(da <= kd[o].mn[i] && abs(da - kd[o].mn[i]) + flag >= ans) return false; if(da >= kd[o].mx[i] && abs(da - kd[o].mx[i]) + flag >= ans) return false; } return true; } void min_distance(int o, point now, int sp, int &ans) { if(!o) return ; now.split = sp; ans = min(ans, get_dis(now, kd[o].p)); int nxt = kd[o].p < now, other_son = 1 ^ nxt; min_distance(kd[o].son[nxt], now, sp ^ 1, ans); int now_dis = abs(kd[o].p.data[sp] - now.data[sp]); if(now_dis < ans && enter(kd[o].son[other_son], ans, now, now_dis, sp)) min_distance(kd[o].son[other_son], now, sp ^ 1, ans); } void insert(int &o, point now, int sp) { if(!o) { create_node(o, now, sp); return ; } now.split = sp; int s = kd[o].p < now; insert(kd[o].son[s], now, sp ^ 1); update(o); if(!need_build(o)) return ; int tot = 0; dfs(o, tot); build(o, 0, tot - 1, sp); } int main() { for(int i = 0; i < maxn - 1; i++) stk[cnt++] = maxn - 1 - i; for(int i = 0; i < 2; i++) { kd[0].mn[i] = INF; kd[0].mx[i] = -INF; } in(n); in(m); kd[0].size = 0; for(int i = 0; i < n; i++) p[i].input(); int root; build(root, 0, n - 1, 0); for(int i = 0, flag, x, y; i < m; i++) { in(flag); in(x); in(y); point nxt(x, y); if(flag == 1) insert(root, nxt, 0); else { int ans = INF; min_distance(root, nxt, 0, ans); out_int(ans); out_char('\n'); } } write(); return 0; }