ODT 学习笔记

news/2025/10/29 21:37:13/文章来源:https://www.cnblogs.com/wusixuan/p/19175032

本文同步发表于 博客园。有问题请不吝指出。

ODT (Old Driver Tree)也叫珂朵莉树(Chtholly Tree),也被叫做是颜色段均摊,由某毒瘤巨佬在 CF896C 中引入。

ODT 是一种暴力数据结构,感觉和 dsu on tree、势能线段树什么的都比较类似,类似暴力的优化。很牛,是不是?

ODT 的核心思想就类似 将值(颜色)相同的一段区间合并为一个元素

其有一些使用场景:

  • 区间赋值,区间查询——可以使用 map 维护相同颜色段以及段信息。

先看个题,然后从中来学习 ODT。

P1840

黄题。

这个题显然有其他方法来做,不过这里就将 ODT 的做法。

题意:在一条数轴上有 \(n\) 个点,分别是 \(1,2,\ldots,n\)。一开始所有的点都被染成黑色。接着我们进行 \(m\) 次操作,第 \(i\) 次操作将 \([l_i,r_i]\) 这些点染成白色。请输出每个操作执行后剩余黑色点的个数。


显然,注意到每次染色后数轴上的点都是黑白相间的。

原本最朴素的暴力是不能通过的,所以我们考虑利用上面的颜色段的性质来对暴力进行优化,也就是减少一些暴力。

假设我们现在要对数轴的红色区间里面进行操作:

image

(由于作者太懒就使用 s 老师的图了)

我们的朴素暴力显然就是在这个区间里面暴力修改。但是实际上并不用这样——我们要开始优化暴力了。

由于颜色是成段的,所以我们发现,对于每一个段,只需要修改这个段的信息即可。

存储颜色段

如果上面的看不懂,可以继续看下面的更加详细的解释。

我们现在只谈修改(也就是说,我们暂时先不考虑查询),看我们如何去实现一下这个暴力。我们可以简单地使用 \((l,w)\) 来表示颜色段信息,\(l\) 为左端点,\(w\) 为值(注意这里的值和颜色不是一个东西,一个颜色段可以维护很多类型的东西)。

例如:

image

因为数轴上每一个点要么是黑要么是白,所以这两个表示方式是可以互化的。即如果应用第二个表示方式,我们照样也可以轻松求出区间的右端点。

注意,这里的最右边还有一个值为 \(-1\) 的东西。这个是为了防止边界溢出,因为左边的 \((38,1)\) 颜色段如果不加以限制的话,我们的算法很有可能把它当作是向右无限延长的。

那么这个东西 \((l,w)\) 该如何记录呢?有一个简单好写的方式就是直接使用 map 来维护。

修改

那么我们该怎么应对修改呢?

例如这样:

image

对区间中的所有数都变成 \(0\)

在操作后,显然区间中的都变成 \(0\) 了,这会导致中间成为一个连续段。而 \([8,19],[38,45]\) 中只有一部分被波及,所以我们不得不修改一下某些颜色段的信息。

image


简单模拟一下,大概就能想出来如何应对修改了。

第一步:先把新的颜色段插入进去。

image

也就是直接二分 \(L,R\) 即可。

第二步:再把中间的颜色段删掉。

image

这个好像真没办法优化。暴力删除。

第三步:把新的颜色段的权值修改成我们想要的值。

就是直接改。

这样,我们的修改就完成了。


考虑分析一下修改的复杂度。答案是 \(O(q \log n)\)\(q\) 为询问个数。为什么呢?

因为,每次操作最多会生成两个结点,然后这些生成的结点也只会被删除一次并在后续访问一次。

而二分和修改 map 都是 \(O(\log n)\),所以最终就是 \(O(q \log n)\)

这意味着,在任何的数据下(可以不是随机数据!),不带查询的 ODT 的速度都极快。这就是暴力数据结构的厉害之处!!


回到 P1840,这个题剩下的就不多了。对于查询黑色点的总数量,每次修改时都动态维护其即可。

简单总结

根据上文对修改和存储的分析,我们可以发现:ODT 实际上真的没啥东西,本质上,就是使用 set/map 来维护颜色段的区间信息,然后其修改和查询就都是在上面做暴力得出的。

个人感觉,暴力数据结构没有改变其朴素、“野蛮”的本质,但是却对各方面效率有了极大的提升。这也许就是暴力数据结构的最大妙处吧。

查询

有修改但没有查询的就是好的 ODT,那是不是意味着有查询的就是不好的 ODT 呢?

容易想到查询的方法。

查询就是再往数组里面塞查询区间的左右两个端点,然后把里面的所有颜色段的权值加起来即可。(注意这里的加是广义的,也就是说可以不是两个数加起来,还可以是两个二元组加起来,类似合并)

image

这个复杂度有点高。但是好像也确实是我们目前可以想到的最好的暴力方法。

这个东西单次复杂度就已经达到了 \(O(\min(q,n) \log n)\) 的级别。好像随便精心构造一下数据都能卡掉……


现在我们发现,如果 ODT 没有查询,那它每次就是 \(\log\) 的,还是一个不错的算法,还算优美,还可以解决很多问题。

但是一碰到多次查询,它就会原地爆炸了……

——等等?我们前面说的能把 ODT 的区间查询卡掉的前提情况,是出题人精心构造了数据。那么出题人不用脑子造数据,或者是数据随机的情况呢?

如果数据是随机的,而且你使用了 map/set 来实现,那么区间查询的理论值是 \(O(q \log \log n)\) 的。

我不会证,只能给个 链接 跑路了。

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

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

相关文章

Aout Me!

一个来自广州市,华南师范大学附属中学的高二学生。 一名普通的 OIer。 主要成就:NOI2025 rk29; Codeforces LGM; 命制了一些你可能做过的题目。轻喷 qwq。

解题报告-游戏(game.*)

游戏 题目描述 Alice 和 Bob 两个人正在玩一个游戏,游戏有很多种任务,难度为 \(p\) 的任务( \(p \in N_{+}\) ),有 \(2^{-p}\) 的概率完成并得到 \(2^{p-1}\) 分,如果完成不了,得 \(0\) 分。 一开始每人都是 \(0\…

gccgo如何实现golang运行时向特定interface的动态conversion(及和C++虚函数表的对比)

gccgo如何实现golang运行时向特定interface的动态conversion(及和C++虚函数表的对比)intro 在阅读k8s的源代码时,发现代码中有一个(一组)很简单粗暴的interface转换:将一个interface(storage对象)尝试向各种类型转换。…

技术人的公关利器:专业新闻稿撰写AI指令深度解析

以前我也是这样,每次写新闻稿都像在写一个没有需求文档的项目,各种要素和结构都要自己摸索。直到我尝试用AI提示词工程的思路来解决这个问题。作为程序员,我们习惯用代码解决技术问题,但面对企业公关、产品发布时却…

2025年最新考勤门禁系统推荐与选型攻略

本文将深度对比8款考勤门禁系统:i人事、 北森、柠檬智联、HID Global、真地(Realand)、Honeywell、TimeClock Plus、ACTi。在企业数字化管理的浪潮中,「考勤门禁系统」已成为人力资源与行政管理的关键基础设施。无…

2026 NOI 做题记录(八)

推荐阅读:A、E、J、K、O、R、S、U、W、ADContest Link \(\text{By DaiRuiChen007}\)*A. [AGC071D] Level K Terms (8) Problem Link 我们声称序列合法当且仅当如下两个条件均满足:定义 \(z_i=\begin{cases}i&i&l…

代码审查API

from fastapi import FastAPI, HTTPException, Depends from pydantic import BaseModel, Field from sqlmodel import SQLModel, Field as SQLField, Session, create_engine, select from typing import List, Optio…

elk架构安装部署

一、elk架构概述概述 ELK是一套开源免费且功能强大的日志分析管理系统,由Elasticsearch、Logstash、Kibana三部分组成,简称ELK ELK可以将系统日志、网站日志、应用系统日志等各种日志进行收集、过滤、清洗,然后进行…

冒泡排序 试做版 2025/10/29 21:13

include <stdio.h> int main() { int n,i,k,p; while(scanf("%d",&n)==1) //读入数组个数n { int arr[n]; //创建数组 该数组刚好能容纳n组数据 for(i=0;i<n;i++) //从数组0开始 数组0 数组…

CSP 45^2复赛游记

DAY -300+ 好激动好激动好激动这是肝硬化学了半年的 \(OI\) ,终于迎来了此生以来第一次考吃薯片-J,去的燕大,然后就是成功翘掉一天课好高兴好高兴!带了 \(inf\) 个零食,包括但不限于:蒟蒻果冻(绿色的,好像是青…

工厂用什么考勤系统好?2025最新8款推荐

本文将深度对比8款工厂考勤系统:i人事、 北森、盖雅实时考勤云、TimeClock Plus、全易通考勤系统、ADP Time & Attendance、同鑫考勤系统、When I Work。在制造业与工业企业中,工厂考勤系统早已成为提升管理效率…

深度技术解析低功耗蓝牙厂商nordic的nRF Connect SDK裸机选项方案

自2018年以来,Nordic Semiconductor一直致力于开发基于Zephyr实时操作系统( RTOS)的nRF Connect SDK,并不断发展,提供最佳的工具与软件,助力开发者在Nordic广泛的无线产品组合上构建高度可扩展的物联网应用。然而,…

MPK(Mirage Persistent Kernel)源码笔记(3)--- 系统接口

MPK(Mirage Persistent Kernel)源码笔记(3)--- 系统接口 目录MPK(Mirage Persistent Kernel)源码笔记(3)--- 系统接口0x00 概述0x01 流程0x02 初始化0x03 定义计算图0x04 编译0x05 执行0xFF 参考 0x00 概述 因…

硬件基础知识和典型应用-在休眠项目中RS485电路休眠设计

硬件基础知识和典型应用-在休眠项目中RS485电路休眠设计<p><iframe name="ifd" src="https://mnifdv.cn/resource/cnblogs/LearnHardware" frameborder="0" scrolling="a…

20232317 2025-2026-1 《网络与系统攻防技术》实验三实验报告

一、实验内容 (1)正确使用msf编码器,veil-evasion,自己利用shellcode编程等免杀工具或技巧。 1.正确使用msf编码器,使用msfvenom生成如jar之类的其他文件 2.veil,加壳工具 3.使用C + shellcode编程 (2)通过组合应用…

用 Gemini + VS Code 打造属于你的 AI 编程神器(完胜 Cursor!)

大家好! 最近很多朋友问我,Cursor + Claude 是不是最强 AI 编程组合? 确实,现在主流的 AI 编程软件中,Cursor 加 Claude Cloud 可以说是“王者中的王炸”。 但问题也很现实——太贵了! 对于刚入门的开发者、小白…

《程序员修炼之道:从小工到专家》观后感第三篇

笔记三:《应对变化——正交性与模块化的灵活设计思维》 核心观点:“正交性”设计能最大化降低代码耦合度,模块化是应对需求变化的“缓冲带”。在业务需求频繁迭代的场景中,正交且模块化的系统能实现“局部修改、全…

profile 与 profile.d 在 Linux 发行版本中的作用 - ENGINEER

profile 与 profile.d 在 Linux 发行版本中的作用​ ​核心概念与作用​​​/etc/profile​:系统范围的登录 Shell 初始化脚本,登录时由 Shell 自动执行,负责设置全局环境变量(如 ​PATH、USER、LOGNAME、HOME、MA…

思维day1

思维day1P6005 [USACO20JAN] Time is Mooney G Bessie 正在安排前往牛尼亚的一次出差,那里有 N(2≤N≤1000)个编号为 1…N 的城市,由 M(1≤M≤2000)条单向的道路连接。Bessie 每次访问城市 i 都可以赚到\(m_{i}\…

内存本地修改

ctrl + esc 可以查看浏览器进程 然后通过CE进行修改内存