\(\mathcal{Description}\)

  Link.

  平面上有 \(n\) 个互不重合的点 \((x_{1..n},y_{1..n})\),求其两两曼哈顿距离的前 \(m\) 小值。

  \(n,m\le2.5\times10^5\)。

\(\mathcal{Solution}\)

  会做,但不完全会做。

  数前 \(k\) 小的一种技术是:将解大致分类,在每类中维护最优解,一起放入堆中迭代。

  应用到本题,按 \((x,y)\) 的二维偏序排序后,对于每个点,尝试维护其前方的所有点与它构成的答案信息。具体地,对于当前 \((x,y)\),维护了 \((x',y')\) 与它的曼哈顿距离,必然有 \(x'\le x\),所以仅需考虑 \(y\) 与 \(y'\) 的关系,分别取正负号,用可持久化线段树维护一发即可。

  复杂度 \(\mathcal O((n+m)\log n)\),空间同阶。

\(\mathcal{Code}\)

  1. /* Clearink */
  2. #include <queue>
  3. #include <cstdio>
  4. #include <vector>
  5. #include <cassert>
  6. #include <iostream>
  7. #include <algorithm>
  8. #define rep( i, l, r ) for ( int i = l, rep##i = r; i <= rep##i; ++i )
  9. #define per( i, r, l ) for ( int i = r, per##i = l; i >= per##i; --i )
  10. typedef long long LL;
  11. #define int LL
  12. typedef std::pair<int, int> PII;
  13. typedef std::pair<LL, int> PLI;
  14. #define fi first
  15. #define se second
  16. inline int rint() {
  17. int x = 0, f = 1, s = getchar();
  18. for ( ; s < '0' || '9' < s; s = getchar() ) f = s == '-' ? -f : f;
  19. for ( ; '0' <= s && s <= '9'; s = getchar() ) x = x * 10 + ( s ^ '0' );
  20. return x * f;
  21. }
  22. template<typename Tp>
  23. inline void wint( Tp x ) {
  24. if ( x < 0 ) putchar( '-' ), x = -x;
  25. if ( 9 < x ) wint( x / 10 );
  26. putchar( x % 10 ^ '0' );
  27. }
  28. inline int iabs( const int a ) { return a < 0 ? -a : a; }
  29. const int MAXN = 2.5e5;
  30. const LL IINF = 1ll << 60;
  31. int n, m, mx, dy[MAXN + 5], root[MAXN + 5];
  32. PII pt[MAXN + 5];
  33. std::vector<int> ybuc[MAXN + 5];
  34. std::priority_queue<PLI, std::vector<PLI>, std::greater<PLI> > heap;
  35. struct SegmentTree {
  36. static const int MAXND = 1e7;
  37. int node, ch[MAXND][2];
  38. PII amn[MAXND], smn[MAXND];
  39. SegmentTree() { amn[0] = smn[0] = { IINF, 0 }; }
  40. inline void copy( const int u, const int v ) {
  41. ch[u][0] = ch[v][0], ch[u][1] = ch[v][1],
  42. amn[u] = amn[v], smn[u] = smn[v];
  43. }
  44. inline void pushup( const int u ) {
  45. amn[u] = std::min( amn[ch[u][0]], amn[ch[u][1]] );
  46. smn[u] = std::min( smn[ch[u][0]], smn[ch[u][1]] );
  47. }
  48. inline void modify( int& u, const int l, const int r,
  49. const int x, const int y ) {
  50. int v = u, mid = l + r >> 1; copy( u = ++node, v );
  51. if ( l == r ) {
  52. if ( x == IINF ) u = 0;
  53. else amn[u] = { -x + dy[y], l }, smn[u] = { -x - dy[y], l };
  54. return ;
  55. }
  56. if ( y <= mid ) modify( ch[u][0], l, mid, x, y );
  57. else modify( ch[u][1], mid + 1, r, x, y );
  58. pushup( u );
  59. }
  60. inline PII query( const int u, const int l, const int r,
  61. const int ql, const int qr, const bool type ) const {
  62. if ( !u ) return { IINF, 0 };
  63. if ( ql <= l && r <= qr ) return type ? amn[u] : smn[u];
  64. int mid = l + r >> 1; PII ret( IINF, 0 );
  65. if ( ql <= mid ) {
  66. ret = std::min( ret, query( ch[u][0], l, mid, ql, qr, type ) );
  67. }
  68. if ( mid < qr ) {
  69. ret = std::min( ret, query( ch[u][1], mid + 1, r, ql, qr, type ) );
  70. }
  71. return ret;
  72. }
  73. inline PLI calc( const int rt, const int x, const int y ) {
  74. PII up( query( rt, 1, mx, y, mx, true ) ),
  75. dn( query( rt, 1, mx, 1, y, false ) );
  76. LL u = 0ll + x - dy[y] + up.fi, d = 0ll + x + dy[y] + dn.fi;
  77. if ( u <= d ) return PLI( u, up.se );
  78. else return PLI( d, dn.se );
  79. }
  80. } sgt;
  81. signed main() {
  82. n = rint(), m = rint();
  83. rep ( i, 1, n ) pt[i].fi = rint(), dy[i] = pt[i].se = rint();
  84. std::sort( pt + 1, pt + n + 1 );
  85. std::sort( dy + 1, dy + n + 1 );
  86. mx = std::unique( dy + 1, dy + n + 1 ) - dy - 1;
  87. rep ( i, 1, n ) {
  88. pt[i].se = std::lower_bound( dy + 1, dy + mx + 1, pt[i].se ) - dy;
  89. ybuc[pt[i].se].push_back( pt[i].fi );
  90. }
  91. rep ( i, 1, mx ) std::sort( ybuc[i].begin(), ybuc[i].end() );
  92. rep ( i, 2, n ) {
  93. root[i] = root[i - 1];
  94. sgt.modify( root[i], 1, mx, pt[i - 1].fi, pt[i - 1].se );
  95. heap.push( { sgt.calc( root[i], pt[i].fi, pt[i].se ).fi, i } );
  96. }
  97. while ( m-- ) {
  98. PLI p( heap.top() ); heap.pop();
  99. wint( p.fi ), putchar( '\n' );
  100. int yv( sgt.calc( root[p.se], pt[p.se].fi, pt[p.se].se ).se );
  101. int x = 0ll + iabs( dy[pt[p.se].se] - dy[yv] ) + pt[p.se].fi - p.fi;
  102. int id = std::lower_bound( ybuc[yv].begin(), ybuc[yv].end(), x )
  103. - ybuc[yv].begin(), nx = id ? ybuc[yv][id - 1] : IINF;
  104. sgt.modify( root[p.se], 1, mx, nx, yv );
  105. heap.push( { sgt.calc( root[p.se], pt[p.se].fi, pt[p.se].se ).fi,
  106. p.se } );
  107. }
  108. return 0;
  109. }

Solution -「JOISC 2021」「LOJ #3491」道路建设的更多相关文章

  1. Solution -「JOISC 2021」「LOJ #3489」饮食区

    \(\mathcal{Description}\)   Link.   呐--不想概括题意,自己去读叭~ \(\mathcal{Solution}\)   如果仅有 1. 3. 操作,能不能做?    ...

  2. Solution -「JOISC 2021」「LOJ #3495」聚会 2

    \(\mathcal{Description}\)   Link.   给定一棵含 \(n\) 个结点的树.称点集 \(S\) 到结点 \(u\) 的会合距离为 \(\sum_{v\in S}\ope ...

  3. Solution -「JOISC 2021」古老的机器

    \(\mathcal{Description}\)   Link.   这是一道通信题.   对于长度为一个 \(n\),仅包含字符 X, Y, Z 的字符串 \(s\),将其中 \(n\) 个字符按 ...

  4. Loj #2731 「JOISC 2016 Day 1」棋盘游戏

    Loj 2731 「JOISC 2016 Day 1」棋盘游戏 JOI 君有一个棋盘,棋盘上有 \(N\) 行 \(3\) 列 的格子.JOI 君有若干棋子,并想用它们来玩一个游戏.初始状态棋盘上至少 ...

  5. 【LOJ】#3036. 「JOISC 2019 Day3」指定城市

    LOJ#3036. 「JOISC 2019 Day3」指定城市 一个点的可以dp出来 两个点也可以dp出来 后面的就是在两个点的情况下选一条最长的链加进去,用线段树维护即可 #include < ...

  6. 【LOJ】#3034. 「JOISC 2019 Day2」两道料理

    LOJ#3034. 「JOISC 2019 Day2」两道料理 找出最大的\(y_{i}\)使得\(sumA_{i} + sumB_{y_i} \leq S_{i}\) 和最大的\(x_{j}\)使得 ...

  7. 【LOJ】#3032. 「JOISC 2019 Day1」馕

    LOJ#3032. 「JOISC 2019 Day1」馕 处理出每个人把馕切成N段,每一段快乐度相同,我们选择第一个排在最前的人分给他的第一段,然后再在未选取的的人中选一个第二个排在最前的切一下,并把 ...

  8. 【LOJ】#3033. 「JOISC 2019 Day2」两个天线

    LOJ#3033. 「JOISC 2019 Day2」两个天线 用后面的天线更新前面的天线,线段树上存历史版本的最大值 也就是线段树需要维护历史版本的最大值,后面的天线的标记中最大的那个和最小的那个, ...

  9. 【LOJ】#3031. 「JOISC 2019 Day1」聚会

    LOJ#3031. 「JOISC 2019 Day1」聚会 听说随机可过? 我想了很久想了一个不会被卡的做法,建出前\(u - 1\)个点的虚树,然后找第\(u\)个点的插入位置,就是每次找一条最长链 ...

随机推荐

  1. CentOS 7 使用unzip解压zip文件提示未找到命令的解决方法

    故障现象: 解决方法: 如果你使用unzip命令解压.zip文件,提示未找到命令,可能是你没有安装unzip软件,下面是安装方法 [root@localhost www]# yum install - ...

  2. vue-json-editor可视化编辑器的介绍与应用

    vue-json-editor可视化编辑器 最近项目中有用到json编辑器,我选用了这款vue的编辑器,看起来也是比较简洁,接下来就具体介绍一下它,以及内部属性. 一.vue-json-editor的 ...

  3. testng 的常用注解

    常用注解如下: @BeforeSuite: 此注解的方法会在当前测试集合中的任一测试用例前执行 @AfterSuite: 此注解的方法会在当前测试集合中的所有测试程序结束后执行 @BeforeTest ...

  4. Oracle update和select 关联

    Oracle update和select 关联 目录 Oracle update和select 关联 1.介绍 2.解决方法 2.1.需求 2.2.错误演示 2.3.解决方法 1.介绍 本文主要向大家 ...

  5. ubuntu安装更换阿里云镜像源

    如果使用apt-get安装软件过慢,可以考虑以下步骤 1.备份 sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak 2.编辑 sudo vi ...

  6. [C 语言基础] 如何调用不同文件中的函数

    很多时候需要将实现不同功能的函数或者与某个模块有关的函数写在一个文件里.这样有两个好处: 1. 方便以后调用:以后需要用到这个模块,或者这类函数,直接将相关文件复制过去,再稍微修改一下就能应用于不同场 ...

  7. 【解决了一个小问题】golang protocol buffers 3中去掉json标签中的omitempty

    参考了这篇帖子:golang protobuf从生成的json标记中删除omitempty标记 由于是在windows上开发,因此写了一个python脚本来解决: remove_tag.py impo ...

  8. k8s-storage-class

    1. 简介 StorageClass 为管理员提供了描述存储 "类" 的方法. 通过StorageClass的定义,管理员可以将存储资源定义为某种类别(Class),正如存储设备对 ...

  9. js复制标题和链接

    问题 常常在写博客和作业时候,需要附上参考链接. 希望可以一键得到标题和链接. 解决方案 普通元素 可以使用findid然后复制 但是标题无法使用 <!DOCTYPE html> < ...

  10. cesium结合geoserver利用WFS服务实现图层编辑(附源码下载)

    前言 cesium 官网的api文档介绍地址cesium官网api,里面详细的介绍 cesium 各个类的介绍,还有就是在线例子:cesium 官网在线例子,这个也是学习 cesium 的好素材. 内 ...