【裸K-D树】BZOJ 2648
来源:互联网 发布:哪的java技术培训好 编辑:程序博客网 时间:2024/05/19 04:54
Problem Description
棋盘上原本有,n个黑棋。
有两种操作:
1 x y 插入一个黑色棋子
2 x y 输出距离这个白色棋子最近的黑色棋子距离(这里的距离是曼哈顿距离)
思路:
参考ldq大佬博客
K-D树,其实就是一个k维的搜索树。这道题k = 2而已。
#include<bits/stdc++.h>using namespace std;const int DIM = 2;//维度,题目是二维const int inf = 0x3f3f3f3f;const int MAX = 500005;struct node{ int l, r; int cd[DIM], maxn[DIM], minn[DIM];//分别代表坐标,以这个结点的为根的子树每一维最大值,和每一维最小值 inline void maintain()//初始化 { l = r = 0; for(int i = 0; i < DIM; i++) maxn[i] = minn[i] = cd[i]; }}tree[2*MAX];int D;//第几维bool operator < (const node &a, const node &b)//重载从小到大{ return a.cd[D] < b.cd[D];}inline void Merge(int mid)//归并,也就是向上更新{ //主要就是为了更新该结点maxn[], minn[] int son[2] = {tree[mid].l, tree[mid].r}; for(int i = 0; i < 2; i++) { if(!son[i]) continue; for(int j = 0; j < DIM; j++) { tree[mid].maxn[j] = max(tree[mid].maxn[j], tree[son[i]].maxn[j]); tree[mid].minn[j] = min(tree[mid].minn[j], tree[son[i]].minn[j]); } }}int build(int l, int r, int now)//建树{ int mid = (l+r)>>1; D = now; nth_element(tree+l, tree+mid, tree+r+1);//D维时,以mid这点为中点,左小 右大 tree[mid].maintain();//初始化 if(l < mid) tree[mid].l = build(l, mid-1, (now+1)%DIM); if(r > mid) tree[mid].r = build(mid+1, r, (now+1)%DIM); Merge(mid);//归并,向上更新 return mid;}int partionMin(int o, int k)//求k这个点,到o这个子树所有点,可能的最小距离值{ int red = 0; for(int i = 0; i < DIM; i++) { if(tree[k].cd[i] > tree[o].maxn[i]) red += tree[k].cd[i] - tree[o].maxn[i]; if(tree[k].cd[i] < tree[o].minn[i]) red += tree[o].minn[i] - tree[k].cd[i]; } return red;}int ans;void Query(int o, int k)//查找距离k这个点最近的距离{ int dm = abs(tree[o].cd[0] - tree[k].cd[0]) + abs(tree[o].cd[1] - tree[k].cd[1]);//曼哈顿距离 if(ans > dm) ans = dm;//更新 int dl = tree[o].l ? partionMin(tree[o].l, k) : inf;//如果左子树存在就求k这个点,到tree[o].l这个子树所有点,可能的最小距离值。否则无穷 int dr = tree[o].r ? partionMin(tree[o].r, k) : inf;// if(dl < dr)//目的优化时间复杂度 { if(dl < ans) Query(tree[o].l, k); if(dr < ans) Query(tree[o].r, k); } else { if(dr < ans) Query(tree[o].r, k); if(dl < ans) Query(tree[o].l, k); }}void Insert(int &o, int k, int now)//插入操作{ if(o == 0)//代表到叶子结点的儿子 { o = k;//更新就好了 return ; } if(tree[k].cd[now] < tree[o].cd[now]) Insert(tree[o].l, k, (now+1)%DIM); else Insert(tree[o].r, k, (now+1)%DIM); Merge(o);}int main(){ int n, m, i, j; while(~scanf("%d %d", &n, &m)) { for(i = 1; i <= n; i++) for(j = 0; j < DIM; j++) scanf("%d", &tree[i].cd[j]); int pos = n + 1; int root = build(1, n, 0); int op; while(m--) { scanf("%d", &op); for(j = 0; j < DIM; j++) scanf("%d", &tree[pos].cd[j]); if(op == 1) { tree[pos].maintain(); Insert(root, pos, 0); pos++; } else { ans = inf; Query(root, pos); printf("%d\n", ans); } } }}
阅读全文
0 0
- 【裸K-D树】BZOJ 2648
- BZOJ 2626 JZPFAR K-D树
- BZOJ 2648 SJY摆棋子 / 2716 Violet 3 天使玩偶 K-D树
- 【BZOJ 2716&2648】[Violet 3]天使玩偶 k-d tree
- BZOJ 2648 SJY摆棋子 K-D Tree
- BZOJ 1941 SDOI 2010 Hide and Seek K-D树
- BZOJ 2626: JZPFAR|K-D tree
- bzoj 4066: 简单题 k-d tree
- bzoj 4520: [Cqoi2016]K远点对 k-d tree
- BZOJ 4605 崂山白花蛇草水 权值线段树+K-D树
- 【K-D树 求最近最远距离】BZOJ 1941 [Sdoi2010]Hide and Seek
- 【K-D树 求矩阵的和】BZOJ-4066 简单题
- [线段树][单调栈] BZOJ 4527 && CF 407E: K-D-Sequence
- K-d树
- k-d树学习
- K-d树详解
- k-D树强烈推荐
- k-d树
- Office 2016 for Mac 免费永久使用方式
- 11.25java作业
- NOR型flash与NAND型flash的区别
- Mysql基本内容之DELETE和TRUNCATE的区别
- Python之enumerate函数
- 【裸K-D树】BZOJ 2648
- 凸包
- bzoj。1008: [HNOI2008]越狱(快速幂 组合数)
- Python 循环语句
- 我的学习记录51
- 11.30周四
- can't set headers after they are sent
- Unity移动平台优化
- selenium测试单选多选按钮