【34.25%】【BZOJ 2648】SJY摆棋子
Time Limit: 20 Sec Memory Limit: 128 MB
Submit: 2718 Solved: 931
[Submit][Status][Discuss]
Description
Input
Output
Sample Input
1 1
2 3
2 1 2
1 3 3
2 4 2
Sample Output
1
2
HINT
kdtree可以过
Source
【题解】
用kdtree来做。
插入的操作的话。可以用数组来模拟指针(不喜欢用,太麻烦)。将kdtree弄成一个类似二叉搜索树的东西。(别管退化的问题了);
然后用两个二维数组ma_x[2],mi_n[2]来维护某个子树里面点的x,y坐标形成的最大矩形的左上角和右下角(不一定存在这样的矩形).
然后我们写估价函数的思路就是,如果要询问的点在这个矩形里面。则估价函数返回一个最小的值0.否则返回这个点到这个矩形的边缘所需要的最小曼哈顿距离。
估价函数这样写。
int gujia_min(int rt)
{
int temp = 0;
for (int i = 0; i <= 1; i++)
{
temp += max(0, op.d[i]-t[rt].ma_x[i]);
temp += max(0, t[rt].mi_n[i] - op.d[i]);
}
return temp;
}
思路是既然这个点在这个子树的矩形内。那最近点就有很大的可能在那个子树里面(不是绝对!);
想象一下一个点被一个矩形包围。那它的最近点“看起来”不就应该是在这个矩形内或者矩形边上吗。
当然我们已经说了。这个是不一定的。你可以很容易举出反例的。
具体实现看代码吧。
【代码】
#include <cstdio>
#include <algorithm> using namespace std; const int MAX_SIZE = 1500000;
const int MAXN = 509000;
const int INF = 2100000000; struct point
{
int d[2];
int ma_x[2], mi_n[2], l, r;
}; point t[MAX_SIZE],p[MAXN],op;
int n, m,totn = 0,root,now,ans; //totn用于创建新的节点。 bool cmp(point a, point b)
{
if (a.d[now] < b.d[now])
return true;
return false;
} void push_up(int rt)
{
int l = t[rt].l, r = t[rt].r;
for (int i = 0; i <= 1; i++)
{
if (l)
{
t[rt].ma_x[i] = max(t[l].ma_x[i], t[rt].ma_x[i]);
t[rt].mi_n[i] = min(t[l].mi_n[i], t[rt].mi_n[i]);
}
if (r)
{
t[rt].ma_x[i] = max(t[r].ma_x[i], t[rt].ma_x[i]);
t[rt].mi_n[i] = min(t[r].mi_n[i], t[rt].mi_n[i]);
}
}
} int build(int begin, int end, int fx)
{
now = fx;
int m = (begin + end) >> 1;
nth_element(p + begin, p + m, p + end + 1, cmp);
int temp = ++totn; //新建的节点要保存下来。
for (int i = 0; i <= 1; i++)
{
t[temp].d[i] = p[m].d[i];
t[temp].ma_x[i] = t[temp].mi_n[i] = p[m].d[i];
}
if (begin < m)
t[temp].l = build(begin, m - 1, 1 - fx);
if (m < end)
t[temp].r = build(m + 1, end, 1 - fx);
push_up(temp);
return temp;
} void input_data()
{
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++)
scanf("%d%d", &p[i].d[0], &p[i].d[1]);
root = build(1, n, 0);
} void insert(int &rt,int fx)
{
if (rt == 0)
{
rt = ++totn;
for (int i = 0; i <= 1; i++)
{
t[rt].d[i] = op.d[i];
t[rt].ma_x[i] = t[rt].mi_n[i] = op.d[i];
}
return;//这里的return不能省略。不然叶子节点也会执行push_up操作。
}
else
if (op.d[fx] < t[rt].d[fx])
insert(t[rt].l, 1 - fx);
else
insert(t[rt].r, 1 - fx);
push_up(rt);//因为插入了元素,修改了点。所以要更新ma_x,mi_n值。
} int get_dis(point a, point b)
{
return abs(a.d[0] - b.d[0]) + abs(a.d[1] - b.d[1]);
} int gujia_min(int rt)
{
int temp = 0;
for (int i = 0; i <= 1; i++)
{
temp += max(0, op.d[i]-t[rt].ma_x[i]);
temp += max(0, t[rt].mi_n[i] - op.d[i]);
}
return temp;
} void query_min(int rt)
{
int dis = get_dis(t[rt], op);
ans = min(ans, dis);
int gl = INF, gr = INF;
int l = t[rt].l, r = t[rt].r;
if (l)
gl = gujia_min(l);
if (r)
gr = gujia_min(r);
if (gl < gr)
{
if (ans > gl)
query_min(l);
if (ans > gr)
query_min(r);
}
else
{
if (ans > gr)
query_min(r);
if (ans > gl)
query_min(l);
}
} void output_ans()
{
for (int i = 1; i <= m; i++)
{
int cs;
scanf("%d%d%d", &cs, &op.d[0], &op.d[1]);
if (cs == 1)
insert(root,0);
else
if (cs == 2)
{
ans = INF;
query_min(root);
printf("%d\n", ans);
}
}
} int main()
{
//freopen("F:\\rush.txt", "r", stdin);
input_data();
output_ans();
return 0;
}
【34.25%】【BZOJ 2648】SJY摆棋子的更多相关文章
- BZOJ 2648: SJY摆棋子
2648: SJY摆棋子 Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 2968 Solved: 1011[Submit][Status][Disc ...
- BZOJ 2648: SJY摆棋子 kdtree
2648: SJY摆棋子 题目连接: http://www.lydsy.com/JudgeOnline/problem.php?id=2648 Description 这天,SJY显得无聊.在家自己玩 ...
- 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摆棋子(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 ...
- bzoj 2648 SJY摆棋子——KDtree
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2648 第一道KDtree! 学习资料:https://blog.csdn.net/zhl30 ...
- bzoj 2648 SJY摆棋子 —— K-D树
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2648 学习资料:https://blog.csdn.net/zhl30041839/arti ...
- BZOJ 2648 SJY摆棋子 ——KD-Tree
[题目分析] KD-Tree第一题,其实大概就是搜索剪枝的思想,在随机数据下可以表现的非常好NlogN,但是特殊数据下会达到N^2. 精髓就在于估价函数get以及按照不同维度顺序划分的思想. [代码] ...
- BZOJ 2648 SJY摆棋子(KD树)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2716 [题目大意] 给出一些点,同时不断插入点和询问某点离插入点最近距离 [题解] 我 ...
随机推荐
- BIND View 加速南北方网络互访
BIND View 加速南北方网络互访 南北方网络互访的问题一直以来就是广大运维人员的心病,两大网络运营商之间的连接带宽比较有限,跟不上互联网业务发展的速度.如何才能 ...
- C#中流,字节,字符,字符串
首先要明白它们本身是由什么组成的: 流:二进制 字节:无符号整数 字符:Unicode编码字符 字符串:多个Unicode编码字符 那么在.net下它们之间如何转化呢? 一般是遵守以下规则: 流-&g ...
- android hander
http://www.cnblogs.com/plokmju/p/android_Handler.html 前言 Android的消息传递机制是另外一种形式的“事件处理”,这种机制主要是为了解决And ...
- MFC中对话框的各种消息触发时间
小结:WM_CREATE是所有窗口都能响应的消息,表明本窗口已经创建完毕.可以安全的使用这个窗口了,例如在它上面画控件等等.这个状态肯定是在调用ShowWindows()显示窗口之前.WM_WM_IN ...
- STM32 输入捕获的脉冲宽度及频率计算
输入捕获模式可以用来测量脉冲宽度或者测量频率.STM32 的定时器,除了 TIM6 和 TIM7,其他定时器都有输入捕获功能.以下是对脉冲宽度及频率的计算. 1.脉冲宽度 如下图所示,采集该高电平脉冲 ...
- 《开源公开课分享》:Java开源框架案例分享
缺乏高端技术人才?缺乏开发标准? 代码复用性低?技术风险难于把控? 招聘成本高?培训成本高? 假设想法不够雄伟,那么就会局限于细节:假设一開始就铺很大的摊子,将会失去控制: ...
- setting.system-全局属性的设定
SystemProperties跟Settings.System 1 使用 SystemProperties.get如果属性名称以“ro.”开头,那么这个属性被视为只读属性.一旦设置,属性值不能改变. ...
- 1.1 Introduction中 Producers官网剖析(博主推荐)
不多说,直接上干货! 一切来源于官网 http://kafka.apache.org/documentation/ Producers 生产者(Producers) Producers publish ...
- django 简单会议室预约(1)
django 是python的一个web框架,为什么要用django,作者之前用过另一个框架flask,虽然flask比较简单很容易让人学,但是flask没有整体感,会让初学着茫然. 这里我们用dja ...
- mysql 语句优化心得
排序导致性能较慢 优化策略:1.尽量不使用排序 2.只查有索引的结果然后 内连接查询 select bizchance0_.* from biz_chance bizchance0_, biz_b ...