2017.3.25 SJY摆石子 思考记录
来源:互联网 发布:ios http网络协议 编辑:程序博客网 时间:2024/04/30 02:54
终于找到了一个kd树的题、、来看看
k-d树原理还是不难的,就是代码技巧比较多可能可读性比较差
它就是把一个平面分成:
找最接近的点原理是利用极值矩形:
这个题就是k-d树板子题了、
下面的注释很详细
码:
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>#define N 1000005#define inf 1000000000 using namespace std;int xycmp,i,n,m,ans,rt,op;struct dian{ //注意:下标范围为[2]的 0指的是x坐标 1指的是y坐标 int xiao[2],da[2],xy[2];}d[N]; //对于d集的:只有xy有用,指每个点读入的坐标 bool cmp(dian x,dian y) { //cout<<xycmp<<" ";return (x.xy[xycmp]<y.xy[xycmp]); //比较的是这一次比较的坐标的大小 }struct kdtree{ int xia[N][2]; //指向这个节点的两个儿子 dian s[N],q; //对于s集的: xiao 指的是矩形左下角的坐标集 da指的是矩形右上角的点集 xy指的是这个点的坐标 void upd(int now) //维护矩形 {int l=xia[now][0],r=xia[now][1]; for(int i=0;i<2;i++)//依次循环 x、y坐标 {if(l){s[now].da[i]=max(s[l].da[i],s[now].da[i]);s[now].xiao[i]=min(s[now].xiao[i],s[l].xiao[i]);} //如果有左儿子,就取一遍左儿子x、y 矩形 的 坐标最值 再取最值 if(r){s[now].da[i]=max(s[r].da[i],s[now].da[i]);s[now].xiao[i]=min(s[now].xiao[i],s[r].xiao[i]);}//如果有右儿子,就取一遍右儿子x、y 矩形 的 坐标最值 再取最值 }}void add(int now,dian t)//添加 {for(int i=0;i<2;i++)s[now].xiao[i]=s[now].da[i]=s[now].xy[i]=t.xy[i];//初始化最大、最小、这个s集(kd树上的) 值都是 当前点的x、y坐标 }int dis(int now){int lin=0; for(int i=0;i<2;i++)lin+=max(s[now].xiao[i]-q.xy[i],0);for(int i=0;i<2;i++)lin+=max(q.xy[i]-s[now].da[i],0);return lin; //这块比较难理解,如果第一个循环>0第二个循环就一定为0 反之亦然 所以它实际上算的是点q到 now点对应的矩形的 曼哈顿距离 }void build(int &k,int l,int r,int xydo)//建kd树 k值要返回,因为没有初值 xydo表示当前比较的什么坐标 0是x 1是y {k=(l+r)>>1; xycmp=xydo; //用k作为编号方便(依次标也没人管你,这不是线段树,可以乱), xycmp是比较的坐标 nth_element(d+l,d+k,d+r+1,cmp); //这几乎是为kd树量身打造的函数,详情自行百度或见我 stl 算法总结 add(k,d[k]); //加入这个中间点 if(l<k)build(xia[k][0],l,k-1,xydo^1); //建左子树 if(r>k)build(xia[k][1],k+1,r,xydo^1); //建右子数 upd(k);//维护矩形 } void ins(int k,int xydo) //插入点 k是当前已有点的编号 { if(q.xy[xydo]<s[k].xy[xydo]) //因为小的在左子树 大的在右子树 { if(xia[k][0])ins(xia[k][0],xydo^1); else xia[k][0]=++n,add(n,q);//没有的话就找到了归宿 加一个 }else{if(xia[k][1])ins(xia[k][1],xydo^1); // else xia[k][1]=++n,add(n,q); // 同上 } upd(k);//不要忘了更新 }void zhao(int k){ans=min(ans,(abs(q.xy[0]-s[k].xy[0])+abs(q.xy[1]-s[k].xy[1])));//答案取这个点和要找点的最小距离 int ld=(xia[k][0])?dis(xia[k][0]):inf;//如果在矩形内部就是0,在外部就是最小距离,没有这个子节点就是inf int rd=(xia[k][1])?dis(xia[k][1]):inf;if(ld<rd){if(ld<ans)zhao(xia[k][0]);if(rd<ans)zhao(xia[k][1]);//用访问顺序来优化(优先访问距离短的来更新答案,这样长的就有可能被卡掉) }else{if(rd<ans)zhao(xia[k][1]);if(ld<ans)zhao(xia[k][0]);}}}kd;int main(){scanf("%d%d",&n,&m);for(i=1;i<=n;i++){scanf("%d%d",&d[i].xy[0],&d[i].xy[1]);}kd.build(rt,1,n,0);for(int i=1;i<=m;i++){scanf("%d%d%d",&op,&kd.q.xy[0],&kd.q.xy[1]);if(op==1){kd.ins(rt,0);}else{ans=inf;kd.zhao(rt);printf("%d\n",ans); }}return 0; }
0 0
- 2017.3.25 SJY摆石子 思考记录
- bzoj2648 SJY摆石子 kd-tree
- BZOJ2648 SJY摆棋子
- bzoj2648 SJY摆棋子
- 【BZOJ2648】SJY摆棋子
- 2648: SJY摆棋子
- bzoj2648 SJY摆棋子
- BZOJ 2648 SJY摆棋子
- BZOJ 2648 SJY摆棋子
- BZOJ 2648 SJY摆棋子
- 【BZOJ2716/2648】SJY摆棋子
- BZOJ 2648 SJY摆箱子
- 【BZOJ2648】SJY摆棋子 KDTree 【数组版!】
- [BZOJ2648]=[BZOJ2716]SJY摆棋子
- Bzoj2648:SJY摆棋子:K-D-Tree
- 【bzoj2648】【sjy摆棋子】【kd树】
- 【34.25%】【BZOJ 2648】SJY摆棋子
- 【BZOJ 2648/2716】SJY摆棋子
- React-Native 之 数据持久化
- 前端面试经典题目合集
- 水仙花数
- 多线程设计模式(一) Single Threaded Execution
- ListView适配器的写法
- 2017.3.25 SJY摆石子 思考记录
- (四)ROS坐标变换可视化(示例运行)
- tensorflow 风格迁移二
- 快速学习javaSE基础1-java概述(了解)
- Splunk 命令学习
- 手把手教你linux下google chrome浏览器root用户无法运行,以及flash插件安装
- 多项式求和
- 抽签
- LabelFlowLayout(流式标签布局)