bzoj2648/2716 SJY摆棋子
传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2648
http://www.lydsy.com/JudgeOnline/problem.php?id=2716
【题解】
直接上kdtree
用查询的最近最远点的那种写法。
估价在上一篇博客。
还不知道过了吗真是傻逼还有人卡评测我日
重构的BLOCK选在最多点数的1/10左右即可。。
成功垫底。
我真是傻逼RE了好几发
build后面和rebuild都要ret。。。
# include <stdio.h> # include <string.h> # include <iostream> # include <algorithm> // # include <bits/stdc++.h> using namespace std; typedef long long ll; typedef long double ld; typedef unsigned long long ull; const int M = 1e6 + 10; const int mod = 1e9+7; # define RG register # define ST static inline void gmin(int &x, int y) {if(x > y) x = y;} inline void gmax(int &x, int y) {if(x < y) x = y;} int D; struct node { int d[2], mi[2], mx[2], l, r; friend bool operator == (node a, node b) { return a.d[0] == b.d[0] && a.d[1] == b.d[1]; } friend bool operator < (node a, node b) { return a.d[D] < b.d[D]; } }a[M], t[M]; # define ls T[x].l # define rs T[x].r int n, m; node tmp; struct KDT { node T[M]; int siz, rt; inline void set() { rt = siz = 0; } inline int getdist(int x, int X, int Y) { return max(T[x].mi[0]-X, 0) + max(X-T[x].mx[0], 0) + max(T[x].mi[1]-Y, 0) + max(Y-T[x].mx[1], 0); } inline void up(int x) { for (int i=0; i<2; ++i) { T[x].mi[i] = T[x].mx[i] = T[x].d[i]; if(ls) gmin(T[x].mi[i], T[ls].mi[i]); if(rs) gmin(T[x].mi[i], T[rs].mi[i]); if(ls) gmax(T[x].mx[i], T[ls].mx[i]); if(rs) gmax(T[x].mx[i], T[rs].mx[i]); } } inline int build(int l, int r, int d) { if(l>r) return 0; int mid = l+r>>1; D = d; nth_element(t+l, t+mid, t+r+1); // printf("mid = %d\n", mid); T[mid] = t[mid]; T[mid].l = build(l, mid-1, d^1); T[mid].r = build(mid+1, r, d^1); up(mid); // printf("%d [%d,%d], [%d,%d], (%d, %d)\n", mid, T[mid].mi[0], T[mid].mx[0], T[mid].mi[1], T[mid].mx[1], T[mid].d[0], T[mid].d[1]); // printf(" ls = %d, rs = %d\n", T[mid].l, T[mid].r); return mid; } inline void insert(int &x, int d) { if(!x) { x = ++siz; for (int i=0; i<2; ++i) T[x].d[i] = T[x].mi[i] = T[x].mx[i] = tmp.d[i]; T[x].l = 0, T[x].r = 0; } if(tmp == T[x]) return ; if(tmp.d[d] < T[x].d[d]) insert(ls, d^1); else insert(rs, d^1); up(x); } int ans; inline void query(int x, int X, int Y) { if(!x) return; int tmp = abs(T[x].d[0]-X) + abs(T[x].d[1]-Y), d[2]; if(ls) d[0] = getdist(ls, X, Y); else d[0] = 2147483647; if(rs) d[1] = getdist(rs, X, Y); else d[1] = 2147483647; gmin(ans, tmp); if(d[0] < d[1]) { if(d[0] < ans) query(ls, X, Y); if(d[1] < ans) query(rs, X, Y); } else { if(d[1] < ans) query(rs, X, Y); if(d[0] < ans) query(ls, X, Y); } } inline int query(int X, int Y) { ans = 2147483647; query(rt, X, Y); return ans; } inline int rebuild(int l, int r, int d) { if(l>r) return 0; int mid = l+r>>1; D = d; nth_element(t+l, t+mid, t+r+1); T[mid] = t[mid]; T[mid].l = rebuild(l, mid-1, d^1); T[mid].r = rebuild(mid+1, r, d^1); up(mid); return mid; } }T; int REBUILD_SIZE = 100000; inline bool cmp(node a, node b) { return a.d[0] < b.d[0] || (a.d[0] == b.d[0] && a.d[1] < b.d[1]); } int main() { // freopen("bzoj2648.in", "r", stdin); // freopen("bzoj2648.out", "w", stdout); scanf("%d%d", &n, &m); for (int i=1; i<=n; ++i) scanf("%d%d", &a[i].d[0], &a[i].d[1]); sort(a+1, a+n+1, cmp); int tn = 0; t[++tn] = a[1]; for (int i=2; i<=n; ++i) if(!(a[i] == a[i-1])) t[++tn] = a[i]; n = tn; REBUILD_SIZE += n; T.siz = n; T.rt = T.build(1, n, 0); int opt, x, y; for (int test = 1; test <= m; ++test) { scanf("%d%d%d", &opt, &x, &y); if(opt == 1) { tmp.d[0] = x, tmp.d[1] = y; T.insert(T.rt, 0); if(T.siz == REBUILD_SIZE) { for (int i=1; i<=T.siz; ++i) t[i] = T.T[i]; T.rt = T.rebuild(1, T.siz, 0); REBUILD_SIZE += 100000; } } else { printf("%d\n", T.query(x, y)); } // cerr << "ok test = " << test << endl; } return 0; }