[Link\frak{Link}Link]


考虑用 cdq 分治解决?
显然依旧分成修改跟查询,考虑一维排序二维cdq?啊但是那显然不太对,cdq能解决三维偏序,
但是她不能解决最近点对啊。平面最近点对并不能这么干。
那我们考虑一点别哒。怎么把题目给出的问题转化成三维偏序?
“最近”点对就有一种偏序的感觉,但是怎么转化呢?
感觉很不好搞?
但是呢,但是呢,如果变成单纯的比较 x y 坐标大小,就很好做了呀?
因为是偏序问题,所以实际上也不好直接这么搞
比如说我们只考虑第三象限
如果简单考虑,对询问 (x,y)(x,y)(x,y) 直接求 xi≤x,yi≤yx_i\le x,y_i\le yxi​≤x,yi​≤y 点中 min⁡(xi−x+yi−y)\min{(x_i-x+y_i-y)}min(xi​−x+yi​−y)
这样对询问的依赖就比较大,
所以我们换一下思路,去掉 xxx 和 yyy 那么
对询问 (x,y)(x,y)(x,y) 只需要求 xi≤x,yi≤yx_i\le x,y_i\le yxi​≤x,yi​≤y 点中 max⁡(xi+yi)\max{(x_i+y_i)}max(xi​+yi​) 。
问题就被简化辣。
一维时间,二维横坐标,三维纵坐标


彳巴
那么只需要把曼哈顿距离拆开变成四个方向(四个象限)就不难搞了errrr
简单吧?(xxx
你可能会说,四个方向搞你马呢
这样,我们换一次方向就把整个图转一遍?
然后cdq的时候只处理在固定方向上的点。


cdq 的话,实际上还可以多加一个优化,就是把一开始的 nnn 个点提出来单独处理。
但是我没有写x


kkk-d tree 的话就是一个裸题了
复杂度:建树 best case O(nlog⁡n)O(n\log n)O(nlogn) ,worst case O(knlog⁡n)O(kn\log n)O(knlogn)
空间复杂度 O(2n)O(2n)O(2n)
插入 O(log⁡n)O(\log n)O(logn) 删除 O(log⁡n)O(\log n)O(logn)
求最近点对 O(nlog⁡n)O(n\log n)O(nlogn) in average ,worst case O(n2)O(n^2)O(n2)
数点 worst case O(kn1−1/k)O(kn^{1-1/k})O(kn1−1/k)
高维空间中,一般 n≫2kn\gg2^kn≫2k 的时候用 kkk-d tree 找最/k近邻效果才会好一点;
实际上维度很高的时候,假如点数不多,求最近邻甚至不如枚举

那 cqoi 那道题跑 kdt 实际上就是玄学卡啦。(虽然的确就是要你 kdt 玄学卡
(不过那题随机化也可以大概大概,就是用那种转系的。。来分界求
虽然现在那种做法有点普及了,(可能?)容易被哈克
一般的最近/远邻也可以用各种骚操作随机卡,比如说
你可以预先确定一个松的下界,排序,某个坐标相差过小就可以去掉
暴枚然后不停更新
当然如果你觉得随机很不稳,又嫌得蛋疼 / 你觉得 kdt 比随机好写
那就大力 kdt 吧,记得多优化一下常数。。
至少基本的板子要足够优吧?(比如我下面那个板子就不是很好

至于这道题用 kdt 复杂度应该是 O(n)O(\sqrt{n})O(n​) 的,因为是每次询问给出点的 k 近邻


cdq
#include<cstdio>
#include<cmath>
#include<cctype>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
inline void setmax(int&a,const int&b)
{if(a<b)a=b;
}
inline void setmin(int&a,const int&b)
{if(a>b)a=b;
}
#define getchar() (frS==frT&&(frT=(frS=frBB)+fread(frBB,1,1<<12,stdin),frS==frT)?EOF:*frS++)
char frBB[1<<12], *frS=frBB, *frT=frBB;
int read()
{char ch = getchar(); bool w = 0; int x = 0;while (!isdigit(ch)) w |= (ch == '-'), ch = getchar();while (isdigit(ch)) x = x * 10 + (ch ^ 48), ch = getchar();return w ? -x : x;
}
const int MAXN = 600005;
const int INF = 0x3f3f3f3f;
int n, m, u;
struct pt
{int x;int y;int id;pt(int b=0, int c=0, int d=0){x = b;y = c;id = d;}bool operator < (const pt& o) const{return x <= o.x;}
}o[MAXN], e[MAXN], sav[MAXN];
int x[MAXN], y[MAXN], tem[MAXN], met[MAXN], bit[1000005], ans[MAXN];
int p, q, tot, r, s;
void Modify(int x, int k)
{while(x<=s){setmax(bit[x], k);x += x & -x;}
}
void Clear(int x)
{while (x<=s){if(bit[x])bit[x]=0;else break;x += x & -x;}
}
int Query(int x)
{int ret = 0;while(x){setmax(ret, bit[x]);x -= x & -x;}return ret;
}
int f;
void cdq(int L, int R)
{if (L == R) return;int Mid = L + R >> 1;cdq(L, Mid);cdq(Mid + 1, R);for (p = L, q = Mid + 1; q <= R; ++q){if (o[q].id){for (; p <= Mid && o[p].x <= o[q].x; ++p){if (!o[p].id) Modify(o[p].y, o[p].x+o[p].y);}f = Query(o[q].y);if(f) setmin(ans[o[q].id],o[q].x+o[q].y-f);}}for (int i = L; i <= p; ++i) if (!o[i].id) Clear(o[i].y);merge(o+L, o+Mid+1, o+Mid+1, o+R+1, e+L);for (int i = L; i <= R; ++i) o[i] = e[i];
}
int rx, ry, rt;
void Del()
{rx=ry=rt=0;for (register int i=1;i<=m;++i)if(o[i].id)setmax(rx,o[i].x),setmax(ry,o[i].y);for (register int i=1;i<=m;++i)if(o[i].x<=rx&&o[i].y<=ry)e[++rt]=o[i];memcpy(o,e,sizeof(e));
}
int main()
{n = read(); m = read();register int *xwhere = x+1, *ywhere = y+1;for (register int i = 1; i <= n; ++i){(*xwhere) = 1+read(), (*ywhere) = 1+read();setmax(r,*xwhere); setmax(s,*ywhere);o[i] = pt(*(xwhere++), *(ywhere++));}m += n;for (register int t, i = n + 1; i <= m; ++i){t = read();(*xwhere) = 1+read(), (*ywhere) = 1+read();setmax(r,*xwhere); setmax(s,*ywhere);o[i] = pt(*(xwhere++), *(ywhere++), (t==2)?(++u):0);}++r; ++s;memcpy(sav,o,sizeof(o));for (int i = 1; i <= u; ++i) ans[i] = INF;Del();cdq(1,rt);memcpy(o,sav,sizeof(sav));for (int i = 1; i <= m; ++i) o[i].x = r-o[i].x;Del();cdq(1,rt);memcpy(o,sav,sizeof(sav));for (int i = 1; i <= m; ++i) o[i].y = s-o[i].y;Del();cdq(1,rt);memcpy(o,sav,sizeof(sav));for (int i = 1; i <= m; ++i) o[i].x = r-o[i].x, o[i].y=s-o[i].y;Del();cdq(1,rt);for (int i = 1; i <= u; ++i) printf("%d\n", ans[i]);return 0;
}

kdt
把我调炸了。。。
#include<cstdio>
#include<cmath>
#include<cctype>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
#define getchar() (frS==frT&&(frT=(frS=frBB)+fread(frBB,1,1<<12,stdin),frS==frT)?EOF:*frS++)
char frBB[1<<12], *frS=frBB, *frT=frBB;
int read()
{char ch = getchar(); int x = 0; bool w = 0;while (!isdigit(ch)) w |= (ch == '-'), ch = getchar();while (isdigit(ch)) x = x * 10 + (ch ^ 48), ch = getchar();return w ? -x : x;
}
#define max(DefVa,DefVb) ((DefVa)>(DefVb)?(DefVa):(DefVb))
#define min(DefVa,DefVb) ((DefVa)<(DefVb)?(DefVa):(DefVb))
#define setmax(DefVa,DefVb) ((DefVb)>(DefVa)?((DefVa)=(DefVb)):0)
#define setmin(DefVa,DefVb) ((DefVb)<(DefVa)?((DefVa)=(DefVb)):0)
#define abs(x) ((x)<0?(-(x)):(x))
const double Alph = 0.75;
const int INF = 0x3f3f3f3f;
const int MAXN = 1000005;
int n, m, Root, cd;
struct pt
{int x, y;pt(int xx=0, int yy=0){x = xx;y = yy;}
}TemStack[MAXN], CorPt[MAXN];
int TemStackTot;
int Child[MAXN][2];
int Siz[MAXN];
int Xmn[MAXN], Xmx[MAXN], Ymn[MAXN], Ymx[MAXN];
int CorId[MAXN];
int Dim[MAXN];
int Rec[MAXN], top, Ntot;
#define NewNode() (top?Rec[top--]:++Ntot)
#define LChild(DefVal) Child[DefVal][0]
#define RChild(DefVal) Child[DefVal][1]
inline bool cmpx(const pt& a, const pt& b) { return a.x < b.x;}
inline bool cmpy(const pt& a, const pt& b) { return a.y < b.y;}
inline void Maintain(const int& x)
{static int l, r;l = LChild(x);r = RChild(x);Siz[x] = Siz[l] + Siz[r] + 1;Xmn[x] = Xmx[x] = CorPt[x].x;Ymn[x] = Ymx[x] = CorPt[x].y;if (l){setmin(Xmn[x], Xmn[l]);setmin(Ymn[x], Ymn[l]);setmax(Xmx[x], Xmx[l]);setmax(Ymx[x], Ymx[l]);}if (r){setmin(Xmn[x], Xmn[r]);setmin(Ymn[x], Ymn[r]);setmax(Xmx[x], Xmx[r]);setmax(Ymx[x], Ymx[r]);}}
int Structure(int L, int R)
{if (L > R) return 0;if (L == R){CorId[L] = NewNode();Dim[CorId[L]] = 0;CorPt[CorId[L]] = TemStack[L];Maintain(CorId[L]);return CorId[L];}static int XMn, XMx, YMn, YMx;XMn = INF, XMx = 0, YMn = INF, YMx = 0;for (register int i = L; i <= R; ++i){setmax(XMx, TemStack[i].x);setmin(XMn, TemStack[i].x);setmax(YMx, TemStack[i].y);setmin(YMn, TemStack[i].y);}int Mid = L + R >> 1;CorId[Mid] = NewNode();(XMx-XMn>=YMx-YMn)?(nth_element(TemStack + L, TemStack + Mid + 1, TemStack + R + 1, cmpx), Dim[CorId[Mid]] = 0):(nth_element(TemStack + L, TemStack + Mid + 1, TemStack + R + 1, cmpy), Dim[CorId[Mid]] = 1);CorPt[CorId[Mid]] = TemStack[Mid];LChild(CorId[Mid]) = Structure(L, Mid - 1);RChild(CorId[Mid]) = Structure(Mid + 1, R);Maintain(CorId[Mid]);return CorId[Mid];}
int temN;
void Destroy(int x)
{if(LChild(x)) Destroy(LChild(x)), LChild(x) = 0;TemStack[++TemStackTot] = CorPt[x];CorId[TemStackTot] = x;Rec[++top] = x;if(RChild(x)) Destroy(RChild(x)), RChild(x) = 0;
}
void Insert(const int& x, const int& y)
{register int Pos = Root, Fa = 0;register bool Belong;while(Pos){setmax(Xmx[Pos], x);setmin(Xmn[Pos], x);setmax(Ymx[Pos], y);setmin(Ymn[Pos], y);++Siz[Pos];Belong = !(Dim[Pos]?(y<=CorPt[Pos].y):(x<=CorPt[Pos].x));if (!Child[Pos][Belong]){Child[Pos][Belong] = temN = NewNode();CorPt[temN] = pt(x,y); Maintain(temN); return;}else if (Siz[Child[Pos][Belong]] + 1 > Siz[Pos] * Alph){TemStackTot = 0; Destroy(Pos);TemStack[++TemStackTot] = pt(x,y);CorId[TemStackTot] = NewNode();if (Pos != Root) Child[Fa][Pos==RChild(Fa)] = Structure(1, TemStackTot), Maintain(Fa);else Root = Structure(1, TemStackTot);return;}else{Fa = Pos;Pos = Child[Pos][Belong];}}
}
inline int CalcDist(int p, int x, int y)
{return max(0,x-Xmx[p])+max(0,Xmn[p]-x)+max(0,y-Ymx[p])+max(0,Ymn[p]-y);
}
int Ans;
inline void Query(int Pos, const int& x, const int& y)
{setmin(Ans, abs(CorPt[Pos].x - x) + abs(CorPt[Pos].y - y));int DisL = LChild(Pos)?CalcDist(LChild(Pos), x, y):INF;int DisR = RChild(Pos)?CalcDist(RChild(Pos), x, y):INF;if(DisL < DisR){if (DisL < Ans) Query(LChild(Pos), x, y);if (DisR < Ans) Query(RChild(Pos), x, y);}else{if (DisR < Ans) Query(RChild(Pos), x, y);if (DisL < Ans) Query(LChild(Pos), x, y);}
}
int main()
{n = read(), m = read();for (register int i = 1; i <= n; ++i) TemStack[i].x=read(), TemStack[i].y=read();TemStackTot = n;Root = Structure(1, n);TemStackTot = 0;for (register int t, x, y, i = 1; i <= m; ++i){t=read(); x=read(); y=read();if (t&1) Insert(x, y);else Ans = INF, Query(Root, x, y), printf("%d\n", Ans);}return 0;
}

[Luogu4169] [Violet]天使玩偶/SJY摆棋子 [cdq分治/k-d tree]相关推荐

  1. P4169 [Violet]天使玩偶/SJY摆棋子 [CDQ分治]

    天使玩偶天使玩偶天使玩偶 Ayu 在七年前曾经收到过一个天使玩偶,当时她把它当作时间囊埋在了地下.而七年后 的今天,Ayu 却忘了她把天使玩偶埋在了哪里,所以她决定仅凭一点模糊的记忆来寻找它. 我们把 ...

  2. [Luogu4169][Violet]天使玩偶/SJY摆棋子

    luogu 题意 一个平面上有\(n\)个点,\(m\)次操作,每次新增一个点,或者是询问离某个点最近的点的距离.这里的距离是曼哈顿距离. \(n,m\le3*10^5\) sol 写一发\(CDQ\ ...

  3. P4169 [Violet]天使玩偶/SJY摆棋子(CDQ分治、暴力)

    解析 之前用KDtree做的一道题 由于懒不想再码一遍了 考虑CDQ分治 关键就是如何拿掉绝对值 如果只维护左下角的,显然就是一个经典的三维偏序问题了 但是本题不一定在左下角,也可能在左上.右下.右上 ...

  4. 题解 洛谷 P4169 [Violet]天使玩偶/SJY摆棋子【CDQ分治】

    题目链接 题意:平面上原有一些点,支持动态加点,动态查询与某个点曼哈顿距离最小的点的距离. 这题据说是有 KD-Tree 和 CDQ 分治两种做法,又据说 KDT 会被卡,于是我采用 CDQ (其实是 ...

  5. [Violet]天使玩偶/SJY摆棋子

    传送门 题目大意就是先给定n个点,然后m个操作,每次添加一个点或者查询离一个点最近的一个点是哪个点. 因为要求的是曼哈顿距离,所以我们先把式子转化一下,就是\((x_i + y_i) - (x_j + ...

  6. 天使玩偶/SJY摆棋子

    P4169 [Violet]天使玩偶/SJY摆棋子 CDQ分治的题目. 我们发现题目要我们求的\(|A_x-B_x|+|A_y-B_y|\)的绝对值号比较恶心. 试想一下怎么去掉 如果所有的点都在我们 ...

  7. 【洛谷P4169】天使玩偶/SJY摆棋子【CDQ分治】

    传送门 题意:动态加点,给定点询问曼哈顿距离最近的点 N,M≤3e5,x,y≤1e6N,M \leq 3e5,x,y \leq 1e6N,M≤3e5,x,y≤1e6 经(kan)过(le)分(ti)析 ...

  8. P4169-[Violet]天使玩偶/SJY摆棋子【CDQ分治】

    正题 题目链接:https://www.luogu.com.cn/problem/P4169 题目大意 nnn个点,然后每次操作 加一个新的点 询问一个点更近的点 解题思路 定义tit_iti​表示第 ...

  9. [BZOJ2716/2648][Violet 3]天使玩偶/SJY摆棋子[KDtree]

    KDtree干这个复杂度是不对的,重构不一定有作用 解释一下的话,因为复杂度是跟size相关的,所以重构作用不大,KDtree在查询最近点对中的作用仅仅是剪枝,可以构造数据使得他遍历O(n)个节点 h ...

最新文章

  1. C++非类型模板参数
  2. 如何及时获得AI顶尖科研团队的最新论文与进展?你需要一份AI内参!
  3. Python 03 学习内容整理
  4. Linux 字符设备驱动开发基础(一)—— 编写简单 LED 设备驱动
  5. html 按钮光束,图文详解,原来3dmax光束特效的制作这么简单!
  6. Android 短信开发学习
  7. mysql分组查询学生平均年龄_mysql练习题
  8. 重磅!贾扬清明日发布新一代云原生数仓与数据湖产品 | 凌云时刻
  9. javassist 学习笔记
  10. Inrie(洪晓军)
  11. netbeans java中文_netbeans中文乱码解决方案
  12. PMP项目进度网络图详解——第1篇:甘特图、PERT
  13. CSS3 背景图 插入 SVG 或图片 base64
  14. 创建 Swift 自定义集合类
  15. Spring学习-Spring核心技术(九)
  16. 人脸识别与膜虹识别_虹膜识别技术和人脸识别技术的区别是什么
  17. 【技巧插件】PDF文件转换为CAD文件
  18. 三菱mr系列服务器故障代码a6,三菱数控系统伺服故障和报警代码大全,超实用!...
  19. TensorFlow实现多层感知器
  20. java 读取excel2007 内存不足_内存不足错误 – 写入Excel时的Java堆空间

热门文章

  1. css 2D转换之旋转rotate
  2. Ueditor 自定义多图上传路径及回显
  3. 学习:赛博空间 Cyberspace 概念
  4. 帆软报表列表_帆软入门与报表设计
  5. CRMEB知识付费V2.1.4免授权版本更新发布
  6. 雅虎财经和新浪财经股票API,中国A股实时和历史数据API获取
  7. 达摩院发布2023十大科技趋势,多领域“日进一寸”式融合创新
  8. 什么是生命周期函数?
  9. 0240 计算机维修技术,0240.2016《计算机维修技术》西南大学网上作业题和答案.doc...
  10. linux memcached默认端口,memcached介绍以及安装