bzoj 2648: SJY摆棋子 KDtree + 替罪羊式重构
KDtree真的很妙啊,真的是又好写,作用还多,以后还需更多学习呀.
对于这道题,我们求的是曼哈顿距离的最小值.
而维护的变量和以往是相同的,就是横纵坐标的最小值与最大值.
我们设为一个极为巧妙且玄学的股价函数.
- int getdis(int o,int x1,int y1){
- int dis = 0;
- if(x1 < node[o].minv[0]) dis += node[o].minv[0] - x1;
- if(x1 > node[o].maxv[0]) dis += x1 - node[o].maxv[0];
- if(y1 < node[o].minv[1]) dis += node[o].minv[1] - y1;
- if(y1 > node[o].maxv[1]) dis += y1 - node[o].maxv[1];
- return dis;
- }
- void query(int o,int x1,int y1){
- int dn = abs(node[o].p[0] - x1) + abs(node[o].p[1] - y1),dl,dr;
- ans = min(ans,dn);
- dl = node[o].ch[0] ? getdis(node[o].ch[0],x1,y1) : inf;
- dr = node[o].ch[1] ? getdis(node[o].ch[1],x1,y1) : inf;
- if(dl < dr) {
- if(dl < ans) query(node[o].ch[0],x1,y1);
- if(dr < ans) query(node[o].ch[1],x1,y1);
- }
- else {
- if(dr < ans) query(node[o].ch[1],x1,y1);
- if(dl < ans) query(node[o].ch[0],x1,y1);
- }
- }
设当前矩阵的边界为 (x1,y1),(x2,y2).
那么对于当前要查询的点 $p$ 如果在矩阵外,那么即使是最近距离也是 $p$ 到最近两个矩阵边界的曼哈顿距离和(getdis函数).
我们将上述最理想化距离设为 $w$,即点 $p$ 到矩阵边界的最小距离.
那么,如果点 $p$ 比当前最优解大的话,那么这一棵子树就没有必要查了.
Code:
- #include <cstdio>
- #include <algorithm>
- #include <cstring>
- #include <cstdlib>
- #define setIO(s) freopen(s".in","r",stdin)
- #define maxn 3000000
- #define inf 100000000
- using namespace std;
- namespace KDtree{
- int tot;
- int d;
- int ans;
- int n;
- int m;
- void init(){ tot = n, ans = inf; }
- int newnode(){ return ++tot; }
- struct Data{
- int ch[2],minv[2],maxv[2],w,sum,p[2];
- }node[maxn];
- bool cmp(Data i,Data j){
- return i.p[d] == j.p[d] ? i.p[d^1] < j.p[d^1]: i.p[d] < j.p[d];
- }
- int isin(int o,int x1,int y1,int x2,int y2){
- if(node[o].minv[0]>=x1&&node[o].maxv[0]<=x2&&node[o].minv[1]>=y1&&node[o].maxv[1]<=y2) return 1;
- return 0;
- }
- int isout(int o,int x1,int y1,int x2,int y2){
- if(node[o].minv[0] > x2 || node[o].maxv[0] < x1) return 1;
- if(node[o].minv[1] > y2 || node[o].maxv[1] < y1) return 1;
- return 0;
- }
- void getmax(int &a,int b){ if( b > a ) a = b; }
- void getmin(int &a,int b){ if( b < a ) a = b; }
- void pushup(int o,int x){
- getmin(node[o].minv[0],node[x].minv[0]);
- getmin(node[o].minv[1],node[x].minv[1]);
- getmax(node[o].maxv[1],node[x].maxv[1]);
- getmax(node[o].maxv[0],node[x].maxv[0]);
- node[o].sum += node[x].sum;
- }
- int build(int l,int r,int o){
- int mid = (l + r) >> 1;
- d = o ; nth_element(node+l,node+mid,node+r+1,cmp);
- node[mid].minv[0] = node[mid].maxv[0] = node[mid].p[0];
- node[mid].minv[1] = node[mid].maxv[1] = node[mid].p[1];
- node[mid].sum = node[mid].w;
- node[mid].ch[0] = node[mid].ch[1] = 0;
- if(l < mid) node[mid].ch[0] = build(l,mid - 1,o ^ 1), pushup(mid,node[mid].ch[0]);
- if(r > mid) node[mid].ch[1] = build(mid + 1, r, o ^ 1), pushup(mid,node[mid].ch[1]);
- return mid;
- }
- void update(int &o,Data x,int de){
- if(!o) {
- o = newnode();
- node[o].p[0] = node[o].maxv[0] = node[o].minv[0] = x.p[0];
- node[o].p[1] = node[o].minv[1] = node[o].maxv[1] = x.p[1];
- return;
- }
- if(x.p[de] < node[o].p[de]) update(node[o].ch[0],x,de^1),pushup(o,node[o].ch[0]);
- else update(node[o].ch[1],x,de^1),pushup(o,node[o].ch[1]);
- }
- int getdis(int o,int x1,int y1){
- int dis = 0;
- if(x1 < node[o].minv[0]) dis += node[o].minv[0] - x1;
- if(x1 > node[o].maxv[0]) dis += x1 - node[o].maxv[0];
- if(y1 < node[o].minv[1]) dis += node[o].minv[1] - y1;
- if(y1 > node[o].maxv[1]) dis += y1 - node[o].maxv[1];
- return dis;
- }
- void query(int o,int x1,int y1){
- int dn = abs(node[o].p[0] - x1) + abs(node[o].p[1] - y1),dl,dr;
- ans = min(ans,dn);
- dl = node[o].ch[0] ? getdis(node[o].ch[0],x1,y1) : inf;
- dr = node[o].ch[1] ? getdis(node[o].ch[1],x1,y1) : inf;
- if(dl < dr) {
- if(dl < ans) query(node[o].ch[0],x1,y1);
- if(dr < ans) query(node[o].ch[1],x1,y1);
- }
- else {
- if(dr < ans) query(node[o].ch[1],x1,y1);
- if(dl < ans) query(node[o].ch[0],x1,y1);
- }
- }
- int main(){
- scanf("%d%d",&n,&m);
- init();
- for(int i = 1;i <= n; ++i) scanf("%d%d",&node[i].p[0],&node[i].p[1]);
- int root = build(1,n,0);
- for(int i = 1;i <= m; ++i) {
- int opt,a,b;
- scanf("%d%d%d",&opt,&a,&b);
- if(opt == 1) {
- Data k;
- k.p[0] = a,k.p[1] = b;
- update(root,k,0);
- if(i % 300000 == 0) root = build(1,tot,0);
- }
- if(opt == 2) {
- ans = inf;
- query(root,a,b);
- printf("%d\n",ans);
- }
- }
- return 0;
- }
- };
- int main(){
- //setIO("input");
- KDtree::main();
- return 0;
- }
bzoj 2648: SJY摆棋子 KDtree + 替罪羊式重构的更多相关文章
- BZOJ 2648: SJY摆棋子 kdtree
2648: SJY摆棋子 题目连接: http://www.lydsy.com/JudgeOnline/problem.php?id=2648 Description 这天,SJY显得无聊.在家自己玩 ...
- bzoj 2648 SJY摆棋子——KDtree
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2648 第一道KDtree! 学习资料:https://blog.csdn.net/zhl30 ...
- BZOJ 2648 SJY摆棋子 ——KD-Tree
[题目分析] KD-Tree第一题,其实大概就是搜索剪枝的思想,在随机数据下可以表现的非常好NlogN,但是特殊数据下会达到N^2. 精髓就在于估价函数get以及按照不同维度顺序划分的思想. [代码] ...
- bzoj 2648: SJY摆棋子&&2716: [Violet 3]天使玩偶 --kdtree
2648: SJY摆棋子&&2716: [Violet 3]天使玩偶 Time Limit: 20 Sec Memory Limit: 128 MB Description 这天,S ...
- BZOJ 2648: SJY摆棋子
2648: SJY摆棋子 Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 2968 Solved: 1011[Submit][Status][Disc ...
- bzoj 2648: SJY摆棋子【KD-tree】
其实理论上cdq更优 核心是依次取x值.y值的mid作为当前节点,向两边递归建立二叉树,树上维护size:子树大小:mx[0/1]:子树内最大x/y:mn[0/1]:子树内最小x/y:d[0/1]:这 ...
- BZOJ 2648: SJY摆棋子(K-D Tree)
Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 6051 Solved: 2113[Submit][Status][Discuss] Descript ...
- bzoj 2648 SJY摆棋子 kd树
题目链接 初始的时候有一些棋子, 然后给两种操作, 一种是往上面放棋子. 另一种是给出一个棋子的位置, 问你离它最近的棋子的曼哈顿距离是多少. 写了指针版本的kd树, 感觉这个版本很好理解. #inc ...
- BZOJ 2648 SJY摆棋子(KD Tree)
http://www.lydsy.com/JudgeOnline/problem.php?id=2648 题意: 思路: KDtree模板题. 参考自http://www.cnblogs.com/ra ...
随机推荐
- word2016如何英汉互译
1.如果是一篇英文文档且是pdf格式,可以用word2016打开直接转化成了word,就算不是会员也可以的,在此附上16版的光盘安装包,可以百度自行下载 (链接:https://pan.baidu.c ...
- 【JavaScript框架封装】使用Prototype给Array,String,Function对象的方法扩充
/* * @Author: 我爱科技论坛* @Time: 20180705 * @Desc: 实现一个类似于JQuery功能的框架* V 1.0: 实现了基础框架.事件框架.CSS框架.属性框架.内容 ...
- Gym-101615D Rainbow Roads 树的DFS序 差分数组
题目链接:https://cn.vjudge.net/problem/Gym-101615D 题意 给一棵树,每个边权表示一种颜色. 现定义一条彩虹路是每个颜色不相邻的路. 一个好点是所有从该节点开始 ...
- [Libre 6282] 数列分块入门 6 (分块)
原题:传送门 code: //By Menteur_Hxy #include<cstdio> #include<iostream> #include<algorithm& ...
- IIS部署ASP.NET网站后提示只有在配置文件或 Page 指令中将 enableSessionState 设置为 true 时,才能使用会话状态...
今天,在IIS上部署网站后,出现了下面错误: 只有在配置文件或 Page 指令中将 enableSessionState 设置为 true 时,才能使用会话状态.还请确保在应用程序配置的 <sy ...
- 【 ACM-ICPC 2018 沈阳赛区网络预赛 D】Made In Heaven
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 点可以重复走的k短路. [代码] #include <bits/stdc++.h> #define LL long lo ...
- UVA11752 The Super Powers
/* UVA11752 The Super Powers https://vjudge.net/contest/153365#problem/Y 数论 注意a^n=b要用除法求,并且求得的n比实际大1 ...
- hdu 1163
别人的代码开始自己不知道什么数论解法: ab*ab=(a*10+b)(a*10+b)=a^2*100+2ab*10+b^2 所以the root digital=(a+b)*(a+b): 而数论中的定 ...
- 轻松学习JavaScript十二:JavaScript基于面向对象之创建对象(一)
这一次我们深入的学习一下JavaScript面向对象技术,在学习之前,必要的说明一下一些面向对象的一些术语. 这也是全部面对对象语言所拥有的共同点.有这样几个面向对象术语: 对象 ECMA-262把对 ...
- jQuery幻灯片插件Owl Carousel
简介 Owl Carousel 是一个强大.实用但小巧的 jQuery 幻灯片插件,它具有一下特点: 兼容所有浏览器 支持响应式 支持 CSS3 过度 支持触摸事件 支持 JSON 及自定义 JSON ...