「K-D Tree 膜板」「BZOJ2648」SJY摆棋子

区块链

581人已加入

描述

这天,SJY显得无聊。在家自己玩。在一个棋盘上,有 N 个黑色棋子。他每次要么放到棋盘上一个黑色棋子,要么放上一个白色棋子,如果是白色棋子,他会找出距离这个白色棋子最近的黑色棋子。此处的距离是 曼哈顿距离 即 |x1x2|+|y1y2| 。现在给出 N500000 个初始棋子。和 M500000个操作。对于每个白色棋子,输出距离这个白色棋子最近的黑色棋子的距离。同一个格子可能有多个棋子。

Input

第一行两个数 N,M
以后 M 行,每行3个数 t x y
如果 t=1 那么放下一个黑色棋子
如果 t=2 那么放下一个白色棋子

Output

对于每个 t=2 输出一个最小距离

Sample Input 2 3 1 1 2 3 2 1 2 1 3 3 2 4 2

Sample Output

1 2 HINT

kdtree 可以过

题解

K-D Tree 膜板题
这里用的是替罪羊式加点,效率更高。

My Code /************************************************************** Problem: 2648 User: infinityedge Language: C++ Result: Accepted Time:17728 ms Memory:48180 kb ****************************************************************/ #include #include #include #include #include #include #define inf 0x3f3f3f3f #define eps 1e-10 using namespace std; typedef long long ll; const ll mod = 1e9 + 7; int Abs(int x){ return x > 0 ? x : -x; } struct point{ int x, y; point(){} point(int _x, int _y){ x = _x; y = _y; } }a[500005]; int cmpx(point a, point b){ return a.x < b.x; } int cmpy(point a, point b){ return a.y < b.y; } struct node{ int x, y, siz, dt; int dx, dy, ux, uy; int lc, rc, fa; }; struct KDTree{ node d[1000005]; int sz, rt, lst, tot; queue<int> q; int newnode(){ if(!q.empty()){ int ret = q.front(); q.pop(); return lst = ret; } return lst = ++sz; } void pushup(int k){ d[k].dx = d[k].ux = d[k].x; d[k].dy = d[k].uy = d[k].y; d[k].siz = 1; if(d[k].lc){ d[k].dx = min(d[k].dx, d[d[k].lc].dx); d[k].dy = min(d[k].dy, d[d[k].lc].dy); d[k].ux = max(d[k].ux, d[d[k].lc].ux); d[k].uy = max(d[k].uy, d[d[k].lc].uy); d[k].siz += d[d[k].lc].siz; } if(d[k].rc){ d[k].dx = min(d[k].dx, d[d[k].rc].dx); d[k].dy = min(d[k].dy, d[d[k].rc].dy); d[k].ux = max(d[k].ux, d[d[k].rc].ux); d[k].uy = max(d[k].uy, d[d[k].rc].uy); d[k].siz += d[d[k].lc].siz; } } void build(int &k, int l, int r, int flag, int fa){ if(l > r) return; k = newnode(); d[k].fa = fa; d[k].dt = flag; // printf("%d %d %d\n", k, l, r); if(l == r){ d[k].x = d[k].dx = d[k].ux = a[l].x; d[k].y = d[k].dy = d[k].uy = a[l].y; return; } int mid = (l + r) >> 1; if(flag) nth_element(a + l, a + mid, a + r, cmpx); else nth_element(a + l, a + mid, a + r, cmpy); d[k].x = a[mid].x; d[k].y = a[mid].y; build(d[k].lc, l, mid - 1, flag ^ 1, k); build(d[k].rc, mid + 1, r, flag ^ 1, k); pushup(k); } int judge(int k){ if((d[d[k].lc].siz + 1) * 0.8 > d[k].siz + 1) return 1; if((d[d[k].lc].siz + 1) * 0.8 > d[k].siz + 1) return 1; return 0; } void dfs(int k){ q.push(k); a[++tot] = point(d[k].x, d[k].y); if(d[k].lc) dfs(d[k].lc); if(d[k].rc) dfs(d[k].rc); } void rebuild(int k){ tot = 0; if(k == rt){ dfs(k); build(rt, 1, tot, 0, 0); return; } int f = d[k].fa, wh = (d[f].rc == k); dfs(k); if(wh) build(d[f].rc, 1, tot, 0, d[f].dt ^ 1); else build(d[f].lc, 1, tot, 0, d[f].dt ^ 1); } void ins(int k, int x, int y, int flag){ if(flag){ if(x <= d[k].x){ if(d[k].lc == 0){ a[1] = point(x, y); build(d[k].lc, 1, 1, flag ^ 1, k); }else ins(d[k].lc, x, y, flag ^ 1); }else{ if(d[k].rc == 0){ a[1] = point(x, y); build(d[k].rc, 1, 1, flag ^ 1, k); }else ins(d[k].rc, x, y, flag ^ 1); } }else{ if(y <= d[k].y){ if(d[k].lc == 0){ a[1] = point(x, y); build(d[k].lc, 1, 1, flag ^ 1, k); }else ins(d[k].lc, x, y, flag ^ 1); }else{ if(d[k].rc == 0){ a[1] = point(x, y); build(d[k].rc, 1, 1, flag ^ 1, k); }else ins(d[k].rc, x, y, flag ^ 1); } } pushup(k); } void ins(int x, int y){ ins(rt, x, y, 0); x = lst; int tmp = 0; while(x != 0){ if(judge(x)) tmp = x; x = d[x].fa; } if(tmp != 0){ rebuild(x); } } int ans; int get(int k, int x, int y){ int ret = 0; ret += max(0, d[k].dx - x); ret += max(0, d[k].dy - y); ret += max(0, x - d[k].ux); ret += max(0, y - d[k].uy); return ret; } void query(int k, int x, int y){ // printf("%d %d %d\n", rt, d[k].x, d[k].y); ans = min(ans, Abs(d[k].x - x) + Abs(d[k].y - y)); int dl = inf, dr = inf; if(d[k].lc) dl = get(d[k].lc, x, y); if(d[k].rc) dr = get(d[k].rc, x, y); if(dl < dr){ if(dl < ans) query(d[k].lc, x, y); if(dr < ans) query(d[k].rc, x, y); }else{ if(dr < ans) query(d[k].rc, x, y); if(dl < ans) query(d[k].lc, x, y); } } int query(int x, int y){ ans = inf; query(rt, x, y); return ans; } }KDT; int n, m; int main(){ //freopen("test.in", "r", stdin); //freopen("test.out", "w", stdout); scanf("%d%d", &n, &m); for(int i = 1; i <= n; i ++){ int x, y; scanf("%d%d", &x, &y); a[i] = point(x, y); } KDT.build(KDT.rt, 1, n, 0, 0); for(int i = 1; i <= m; i ++){ int opt, x, y; scanf("%d%d%d", &opt, &x, &y); if(opt == 1){ KDT.ins(x, y); }else{ printf("%d\n", KDT.query(x, y)); } } return 0; }

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 相关推荐

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分