似乎题解区并没有 cdq 套 cdq 的作法,刚好今天讲了,就来写一发。

题意与记号

题目讲的很清楚了。此方法并没有树状数组好想也没有其高效,但能很方便扩展。下文记原序列为 ddd,将每个点拆分成点与询问,内部增加一个名为 ididid 的数据,若其为 −1-11,则是点,否则是询问。

使用类 c++ 数组的书写方式,否则角标太复杂实在不好看。下文先讲二维再讲三维。

二维偏序

先对 xxx 维排序,再分治 yyy 维,每一次分治中点为 midmidmid 的区间 [l,r)[l,r)[l,r),我们都能保证,也必须保证 d[a].x≤d[b].xd[a].x\le d[b].xd[a].xd[b].xa∈[l,mid)a\in[l,mid)a[l,mid)b∈[mid,r)b\in[mid,r)b[mid,r)
L={d[l],d[l+1],d[l+2],… } ⁣ ⁣ ⁣ ⁣ ⁣ ⁣ ⁣ ⁣ ⁣ ⁣ ⁣ ⁣ ⁣ ⁣ ⁣ ⁣ ⁣ ⁣ ⁣ ⁣ ⁣ ⁣ ⁣ ⁣↑R={d[mid],d[mid+1],… } ⁣ ⁣↑ L=\{d[l],d[l+1],d[l+2],\dots \} \\ \!\!\!\!\!\!\!\!\!\!\!\!\!\!\!\!\!\!\!\!\!\!\!\! \uparrow \\ R=\{d[mid],d[mid+1],\dots \} \\ \!\! \uparrow L={d[l],d[l+1],d[l+2],}R={d[mid],d[mid+1],}
我们对两边同时向后处理(并非同步),我们正在处理 d[a]d[a]d[a]d[b]d[b]d[b],其中 d[a].id=−1d[a].id=-1d[a].id=1d[b].id≠−1d[b].id\ne-1d[b].id=1(其它情况不用考虑)。

如果 d[a].y≤d[b].yd[a].y\le d[b].yd[a].yd[b].y,由于分治,LLLRRR 内以 yyy 为关键字肯定是有序的,所以 d[a′].y≤d[b′].yd[a'].y\le d[b'].yd[a].yd[b].ya′∈[l,a]a'\in[l,a]a[l,a]b′∈[b,r]b'\in[b,r]b[b,r]

所以此时我们便可以记录 d[a]d[a]d[a] 的贡献(这里是 111),并将 d[a]d[a]d[a] 扔到归并排序的辅助数组里, a←a+1a \leftarrow a+1aa+1

同理,如果 d[a].y>d[b].yd[a].y > d[b].yd[a].y>d[b].y,我们直接由之前的贡献总和便可以计算答案,并将 d[b]d[b]d[b] 扔到归并排序的辅助数组里,b←b+1b\leftarrow b+1bb+1

三维偏序

进入正题,仿照上面的方法,在第一次 cdq 内部,每一层再执行另一种 cdq(cdq2),如果我们能保证 LLLRRR 内部同时关于 xxxyyy 有序就好了,可是我们在分治的过程中必然会将 xxx 打乱,如果有一种方法,能告诉我们 xxx 曾经在哪边,便能够解决这个问题。

也就是说:我们只想要曾经(xxx 维)在左边点的对右边询问的做贡献。

为此,我们扩展 ddd,加入一个名为 tagtagtag 的数据表示在当层是在左边还是右边,由于此时 yyy 早已有序,仿照二维进行 cdq2。
解释见代码吧,超详细的!

namespace PB {node d[N];                                             // 存储当前处理的节点数组,包含点和查询void solve(int l, int r) {                             // 处理区间 [l, r) 的 z 维偏序if (l == r - 1) return;                            int mid = (l + r) >> 1;                            solve(l, mid), solve(mid, r);                      int a = l, b = mid, c = l, sum = 0;                // sum 记录左边点的数量while (a < mid || b < r) {                         // 归并排序,按 z 坐标合并if (b == r || (a < mid && d[a].z <= d[b].z)) { // 左边还有元素且 z 更小(或右边已空)if (d[a].id == -1 && d[a].tag == LEFT)     // 如果是左边区间的一个点++sum;                                 tp[c++] = d[a++];                          } else {                                       // 右边 z 更小(或左边已空)if (d[b].id != -1 && d[b].tag == RIGHT)    // 如果是右边区间的查询anst[d[b].id] += sum;                  // 累加当前左边点的数量到查询结果tp[c++] = d[b++];                          }}copy(tp + l, tp + r, d + l); // 将临时数组复制回原数组,完成归并}
} // namespace PBnamespace PA {void solve(int l, int r) {                             // 处理区间 [l, r) 的 y 维偏序if (l == r - 1) return;                            int mid = (l + r) >> 1;                            solve(l, mid), solve(mid, r);                      // 递归处理左半区间 [l, mid) 和右半区间 [mid, r)int a = l, b = mid, c = l;                         // a, b 分别指向左右区间,c 指向临时数组while (a < mid || b < r) {                         // 归并排序,按 y 坐标合并if (b == r || (a < mid && d[a].y <= d[b].y)) { // 左边还有元素且 y 更小(或右边已空)d[a].tag = LEFT, tp[c++] = d[a++];         // 标记为左区间} else {                                       // 右边 y 更小(或左边已空)d[b].tag = RIGHT, tp[c++] = d[b++];        // 标记为右区间}}copy(tp + l, tp + r, d + l);     // 将临时数组复制回原数组,完成 y 维归并copy(tp + l, tp + r, PB::d + l); // 将排序后的数组复制到 PB 命名空间的 d 数组PB::solve(l, r);                 // 调用 PB 处理 z 维偏序}
} // namespace PA

时间复杂度

PB 中一次处理长度为 nnn 的区间 O(n)=nlog⁡nO(n)=n\log nO(n)=nlogn

PA(总):O(∑i=0log⁡nT(n2i)×2i)=O(nlog⁡2n)O(\sum_{i=0}^{\log n}T(\frac{n}{2^i})\times 2^i) = O(n\log^2n)O(i=0lognT(2in)×2i)=O(nlog2n)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/918001.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/918001.shtml
英文地址,请注明出处:http://en.pswp.cn/news/918001.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Effective C++ 条款27: 尽量用const、enum、inline替换 #define

Effective C 条款27&#xff1a;尽量用const、enum、inline替换#define核心思想&#xff1a;使用编译器&#xff08;const, enum, inline&#xff09;替代预处理器&#xff08;#define&#xff09;&#xff0c;让编译器进行语义检查&#xff0c;避免宏替换引发的错误和调试困难…

芯谷科技--高效噪声降低解决方案压缩扩展器D5015

在无绳电话系统中&#xff0c;噪声降低是提升通话质量的关键。 D5015 压缩扩展器&#xff0c;通过集成压缩器和扩展器&#xff0c;有效降低了传输噪声&#xff0c;同时保持了信号的完整性。D5015 采用 SOP20 和 DIP20 封装形式&#xff0c;具有低电压工作、低功耗、高集成度等特…

LabVIEW车床静刚度自动测

​基于LabVIEW 平台开发车床静刚度自动测试系统&#xff0c;针对传统生产法测量中人工误差大、计算复杂、效率低等问题&#xff0c;结合误差复映规律与刚度方程&#xff0c;通过高精度硬件与软件协同&#xff0c;实现试件加工前后尺寸的在线采集、自动计算与报告生成&#xff0…

汽车流通行业4S门店生存性指标:零服吸收率

我们在做汽车4S集团的商业智能BI数据分析项目中&#xff0c;对于4S店的管理&#xff0c;大家经常会提到一个分析指标&#xff0c;叫“零服吸收率”&#xff0c;这个大概是什么意思呢&#xff1f;简单来说就是4S门店一台车都没有卖出的情况下&#xff0c;光靠售后服务部分的收益…

第一性原理科学计算服务器如何选择配置-CPU选择篇

一、 大多数人知道的 (显性因素)核心数与线程数 (Core Count & Thread Count): 重要性&#xff1a; 核心是王道。 科学计算任务&#xff08;如仿真、建模、数据分析、机器学习训练&#xff09;绝大多数都高度并行化&#xff0c;可以同时利用多个核心进行计算。选择建议&…

Java 后端 + JavaScript 前端 实现按钮级别权限控制的解决方案

Java JavaScript 前后端协同实现按钮权限控制 在后台管理系统中&#xff0c;不同用户根据角色和数据状态应展示不同的操作按钮&#xff0c;比如编辑、删除、审批、提交等操作。本文将介绍一种通过 Java 后端生成按钮权限 JSON&#xff0c;前端通过 jQuery 解析控制按钮显示的…

RAG面试内容整理-18. 向量量化与索引压缩技术(PQ, HNSW 等)

当知识库规模达到百万甚至数亿级文档时,向量索引的存储和查询效率成为关键瓶颈。向量量化是一类用较低比特表示近似向量的方法,大幅压缩内存占用并加速相似度计算。PQ(Product Quantization)是其中最著名的方法之一,被Faiss等库广泛实现。PQ的思想是将高维向量划分为多个子…

如何显示一个 Elasticsearch 索引的字段

作者&#xff1a;来自 Elastic JD Armada 学习如何使用 _mapping 和 _search API、子字段、合成 _source 和运行时字段来显示 Elasticsearch 索引的字段。 更多阅读&#xff1a; Elasticsearch&#xff1a;从搜索中获取选定的字段 fields Elasticsearch&#xff1a;inverted …

vue3父组件把一个对象整体传入子组件,还是把一个对象的多个属性分成多个参数传入

以一个对象整体传入时&#xff0c;对象的定义&#xff1a;<template><div><p>姓名: {{ userInfo.name }}</p><p>年龄: {{ userInfo.age }}</p><p>邮箱: {{ userInfo.email }}</p></div> </template> <script s…

【unitrix数间混合计算】2.1 数间混合计算模块(src/number/mod.rs)

一、源码 这段代码是一个Rust模块的声明和导出配置&#xff0c;主要用于实现"类型级数与基本类型混合计算"的功能。 //! 类型级数与基本类型混合计算// 模块声明 // -------------------------------- mod types; // 结构体定义 mod normalize; …

脱机部署k3s

离线部署 K3s 文档 1. 准备工作 操作系统准备&#xff1a;确保服务器已安装好基础操作系统&#xff08;Ubuntu、CentOS 等&#xff09;。关闭防火墙或放通端口&#xff1a;建议关闭防火墙或确保 6443、10250 等端口已开放。准备离线资源文件&#xff1a; 下载地址 k3s-airga…

[失败记录] 使用HBuilderX创建的uniapp vue3项目添加tailwindcss3的完整过程

写在前面 放弃了。。。 1&#xff09;方案1 - 参考下面的“完整步骤” - 安装成功&#xff0c;运行成功&#xff0c;但是&#xff01;好多class不生效&#xff01; 2&#xff09;方案2 - 不安装tailwindcss&#xff0c;直接使用独立的编译好的完整css文件&#xff01; …

使用Idea去git项目,发现拉取和推送都很慢的问题

在大多数情况下&#xff0c;用Idea去对项目进行拉取和推送是很方便的&#xff0c;对于新手来说也是非常友好的但是最近博主遇到了一个问题&#xff0c;就是我feat一个简单的类&#xff0c;去提交推送都需要很长的时间&#xff0c;甚至是20分钟&#xff0c;博主去找了很多方法。…

无人机图传的得力助手:5G 便携式多卡高清视频融合终端的协同应用

前言在无人机作业中&#xff0c;图传系统是连接空中与地面的关键纽带&#xff0c;而 5G 便携式多卡高清视频融合终端虽不直接搭载于无人机&#xff0c;却能通过地面协同突破传统微波图传的局限&#xff0c;为无人机远程监控、应急指挥提供稳定高效的传输支撑。型号&#xff1a;…

【博客系统UI自动化测试报告】

博客系统UI自动化测试报告一、项目背景二、测试内容(一)测试用例(二)测试账号(三&#xff09;使用Selenium进行Web自动化测试1.环境搭建2.创建浏览器驱动3.编写博客登陆模块的测试用例代码4.编写博客主页展示模块的测试用例代码5.编写博客创作模块的测试用例代码6.编写博客查看…

简单手写Transformer:原理与代码详解

Transformer 作为 NLP 领域的里程碑模型&#xff0c;彻底改变了序列建模的方式。它基于自注意力机制&#xff0c;摆脱了 RNN 的序列依赖&#xff0c;实现了并行计算&#xff0c;在机器翻译、文本生成等任务中表现卓越。本文将从零开始&#xff0c;手写一个简化版 Transformer&a…

Numpy科学计算与数据分析:Numpy入门之数组操作与科学计算基础

Numpy入门实践&#xff1a;从零开始掌握科学计算利器 学习目标 通过本课程的学习&#xff0c;学员将了解Numpy的历史背景、核心特点及其在科学计算中的重要性。学员将掌握如何使用Numpy进行数组操作&#xff0c;包括数组的创建、索引、切片以及基本的数学运算&#xff0c;为后…

python:讲懂决策树,为理解随机森林算法做准备,以示例带学习,通俗易懂,容易理解和掌握

为什么要讲和学习决策树呢?主要是决策树(包括随机森林算法)不需要数据的预处理。现实世界的数据往往“脏乱差”,决策树让你在数据准备上可以少花很多功夫,快速上手,用起来非常的“省心”。总之,决策树是机器学习领域里最直观易懂、解释性最强、应用最广泛的基础模型之一…

C语言:单链表学习

文件&#xff1a;main.c #include "linkedList.h"int main(int argc, char *argv[]) {// 创建头结点NODE *head NULL;// 创建链表if (llist_create(&head, 666) < 0){perror("链表创建失败&#xff01;");return -1;}// 向链表插入数据llist_addTa…

使用 decimal 包解决 go float 浮点数运算失真

文章目录问题解决注意问题 go float 在运算的时候会出现精度问题 package mainimport ("fmt" )func main() {var a float64 0.3var b float64 0.6fmt.Println("ab", ab) // 你以为是 0.9 但是结果是&#xff1a;0.8999999999999999 }你观察到的 0.3 …