珂朵莉树/ODT 学习笔记

起源自 CF896C。珂朵莉yyds!

核心思想

把值相同的区间合并成一个结点保存在 set 里面。

用处

骗分。只要是有区间赋值操作的数据结构题都可以用来骗分。在数据随机的情况下一般效率较高,但在不保证数据随机的场合下,会被精心构造的特殊数据卡到超时。

如果要保证复杂度正确,必须保证数据随机。详见 Codeforces 上关于珂朵莉树的复杂度的证明。

更详细的严格证明见 珂朵莉树的复杂度分析。对于 add,assign 和 sum 操作,用 set 实现的珂朵莉树的复杂度为 O(nlog⁡log⁡n)O(n \log \log n)O(nloglogn),而用链表实现的复杂度为 O(nlog⁡n)O(n \log n)O(nlogn)。

正文

存储:每个树上节点都是一个区间,因为权值相同,于是要记录 l,r,vall,r,vall,r,val 。

struct node{I l,r;mutable int val;//可变的 val ,这么写是习惯,为了后续修改/访问操作friend bool operator <(node a,node b){return a.l<b.l;}//在 set 里面,应该比较区间左端点。以便之后查找区间并且 split 。
};set<node>s;

核心操作:split ,含义:把原来为 [l,r] 的这个节点分离成 [l,x) [x,r] ,并且返回这个 [x,r] 区间的迭代器。(可以直接使用 lower_bound)

auto split(I x){auto it=s.lower_bound({x,0,0});//在 set 之中查找 x ,因为只比较左端点所以另外两项可以随便填if(it!=s.end()&&it->l==x)return it;//如果正好找到了一个左端点为 x 的就直接返回。--it;auto p=*it;s.erase(it);//迭代器向左移动一位的区间才有可能被分裂,用 p 记录该迭代器,并且删除现在代表的区间s.insert(node{p.l,x-1,p.val});//把这个区间(存在 p 里面了)分裂return s.insert(node{x,p.r,p.val}).first;//同上,返回右边所指的迭代器,insert 的返回值是一个 pair ,它的返回值 first 是迭代器,second 是一个 bool ?
}

核心操作:assign,含义:把区间 [l,r] 赋值成为 val 。

void assign(I l,I r,I x){auto itr=split(r+1),itl=split(l);//先分裂出 [r+1,+inf] 的右边界,才能分离出 [l,r] 的可行部分,itl->l 就是 l(这个写分裂合并数据结构的大概都知道)s.erase(itl,itr);//这个是前闭后开的,删除了 itl...itr-1 的区间、迭代器s.insert(node{l,r,x});//插入一个全新的区间
}

普通操作:直接从左往右遍历珂朵莉树。

void count(I l,I r){auto itr=split(r+1),itl=split(l);for(;itl!=itr;++itl)//这个也是前闭后开的//do something...
}

习题

P4979 矿洞:坍塌

题意:区间推平,单点查询,判断区间颜色是否统一。

做法

做这道题先来练手。

首先区间推平只需要 assign 即可。

单点查询?只需在 set 之中二分位置即可。

判断区间颜色是否单一?只需按照上文 count 操作即可。(还有点小优化:如果合法就可以直接统一为一个区间)


CF1638E Colorful Operations

题意:每个数有两种属性,一种颜色,一种权值。

区间颜色推平;全局某种颜色所有数的加上一个数;单点查询权值。

做法

首先观察因为颜色是不连续的区间,所以不可能一个个去查找并给它加上权值。

于是就给颜色 ttt 打上标记 bz[t]bz[t]bz[t] 表示当前 ttt 颜色操作之中累加到了多少,因为不断更新很费事。

而 aaa 数组就缓慢更新,只有改变了颜色才更新,这样一个节点的真实值就是 a[i]+bz[col[i]]a[i]+bz[col[i]]a[i]+bz[col[i]] 。

如何求一个 ppp 从 ccc 颜色修改至 c′c'c′ 颜色对其答案的贡献呢?

因为它的真实值是 a[i]+bz[c]a[i]+bz[c]a[i]+bz[c] ,所以先算了 bz[c]bz[c]bz[c] 的帐,即加上 bz[c]bz[c]bz[c] ;

但是它不能直接存储真实值,所以要减去 bz[c′]bz[c']bz[c′] 。

在 ODT 上每个节点都是一段区间,所以考虑使用树状数组维护。

总而言之,操作1就珂朵莉树上面的 assign 操作和区间加;操作2直接 O(1) 改变标记;操作3就直接树状数组查询权值+珂朵莉树查询颜色。


CF343D Water Tree

题意:树上推平子树;树上推平路径;单点查询。

做法

观察到本题只有区间推平和单点查询操作,所以珂朵莉树维护。

树上的操作通过树剖即可解决。


6362.【NOIP2019模拟2019.9.18】数星星(star)

题意:给 nnn 个点有点权,有 mmm 条路径,有 qqq 次操作查询 [l,r][l,r][l,r] 条路径的并的点权之和是多少。

(编者强烈建议搞定 CF343D 和 CF1638E 再来处理本题)

做法

看这么一个东西:HH的项链,就是区间统计个数,相同的只统计一次。

因为可以离线,所以按照 rrr 递增排序,不断加入 rrr ,然后更新一下每个数最后出现在哪里(其实就是权值等于 a[r]a[r]a[r] 的数)。对于 [l,r][l,r][l,r] 询问,查询最晚出现位置大于 l−1l-1l−1 的数的个数。

然后考虑迁移到这题之中:也是离线下来,按照 rrr 递增排序,不断加入 rrr ,然后更新一下每个点最后出现在第几个询问。对于 [l,r][l,r][l,r] 依旧是查询最晚出现位置大于 l−1l-1l−1 的点。对于一条路径更新路径上所有点最晚出现位置,查询所有最晚出现位置大于 l−1l-1l−1 的点权之和

再写得显然一些,树链剖分之后(即在 dfs 序上做区间操作),区间推平;查询大于等于 lll 的数的权值之和(可以转化成小于等于 l−1l-1l−1 数的个数,初始出现位置 000 就好)。

这个大于等于 lll 的数的点权之和就可以直接丢进树状数组里面处理;对于区间推平,直接使用 ODT 维护即可。因为 ODT 把每个区间压缩成为了一个点,所以加减的话也要直接加减这个区间的点权之和。因为是被推平,所以要减去之前的贡献,增加现在的贡献(和 CF1638E 一样)。

实现就显而易见了。


课后练习题

CF896C Willem, Chtholly and Seniorious 万 恶 之 源

CF915E Physical Education Lessons 比模板题还简单 都是暴力有什么难的

CF817F MEX Queries 和上题差不多,但是值域超大,珂朵莉树能做

P5350 序列 平衡树的题和珂朵莉树有什么关系?

CF1423G Growing flowers *3500?*800!

珂朵莉树/ODT 学习笔记相关推荐

  1. [python刷题模板] 珂朵莉树 ODT (基于支持随机访问的跳表

    [python刷题模板] 珂朵莉树 ODT (基于支持随机访问的跳表) 一. 算法&数据结构 1. 描述 2. 复杂度分析 3. 常见应用 4. 常用优化 二. 模板代码 0. 区间推平(lg ...

  2. [python刷题模板] 珂朵莉树 ODT(20220928弃用,请看新文)

    [python刷题模板] 珂朵莉树 ODT (基于SortedList 20220928弃用,请看新文) 一. 算法&数据结构 1. 描述 2. 复杂度分析 3. 常见应用 4. 常用优化 二 ...

  3. [转]我的数据结构不可能这么可爱!——珂朵莉树(ODT)详解

    参考资料: Chtholly Tree (珂朵莉树) (应某毒瘤要求,删除链接,需要者自行去Bilibili搜索) 毒瘤数据结构之珂朵莉树 在全是珂学家的珂谷,你却不知道珂朵莉树?来跟诗乃一起学习珂朵 ...

  4. 浅谈珂朵莉树(ODT)

    前言 珂学家狂喜( 文章目录 前言 一.珂朵莉树来源 二.珂朵莉树 1.珂朵莉树有什么用? 2.原理是什么? a.存储 b.分割结点 c.推平 d.剩余操作 3.复杂度分析 三.珂朵莉树例题 1.P4 ...

  5. 珂朵莉树(odt老司机树)

    传送门 题意:对于一段区间一共有四种操作: 题解:珂朵莉树板题 珂朵莉树,又称Old Driver Tree(ODT).是一种基于std::set的暴力数据结构. 关键操作:推平一段区间,使一整段区间 ...

  6. Chtholly Tree (珂朵莉树) ODT

    ODT,OldDriverTree,又名ChthollyTree O D T , O l d D r i v e r T r e e , 又 名 C h t h o l l y T r e e ODT ...

  7. 算法自学__珂朵莉树

    参考资料: https://zhuanlan.zhihu.com/p/106353082 https://blog.csdn.net/CC_dsm/article/details/98166835 珂 ...

  8. 【日志】珂学——珂朵莉树

    珂朵莉树 (珂学) 珂朵莉树(或者老司机树)起源于CF896C. 由于之前做到每一组数据都要另外开数据结构,所以现在一些东西就会写为class包装 前置知识点 STL中set的使用(list也行,但是 ...

  9. 一种黑科技:珂朵莉树

    首先要明白的是:珂朵莉树(ODT)是一种用来骗分的暴力数据结构. 珂朵莉树的思想是利用集合set,把相同且连续的元素合并为一个个区间,从而进行区间修改:因此,珂朵莉树是区间的集合,这点可以通过定义结构 ...

最新文章

  1. 给一个ul列表中点击到的li赋予样式
  2. 机器学习中的EM算法具体解释及R语言实例(1)
  3. TensorFlow2简单入门-三维张量
  4. Windows 10安装CUDA10.1+cudnn7.6.0+Pytorch1.3.0
  5. 在MFC中添加用户自定义消息
  6. 女孩子应该养成的好习惯
  7. c#打印,输出一句话
  8. Android开发入门二之AndroidManfest.xml文件详细说明 .
  9. 记一次mongdb搭建复制集的小故障
  10. services.xml应该放在项目的哪里_新轮胎应该放在前轮还是后轮?
  11. 转帖:Three Ways to Inject Your Code into Another Process
  12. Quartz-第四篇 常规quartz的使用
  13. 自定义Toast的出现样式
  14. C#打印代码运行时间
  15. Microsoft Office Visio 2007 简体中文专业版
  16. CAN和CAN FD
  17. C#使用Socket实现一个socket服务器与多个socket客户端通信
  18. 翻译官方Vellum教程:Breaking and tearing(破裂撕开)
  19. 关于jmstudio 调用本地摄像头的问题
  20. 计算机无法打开这个应用,win10照片应用打不开提示“无法打开这应用”如何解决...

热门文章

  1. MobileRuler项目(手机尺子)
  2. 努力营造中国ERP产业技术发展的良好环境(转)
  3. 014 SQL注入魔鬼五步走
  4. 如何使excel的图表实现自动更新月和周?
  5. HP OpenView 的安装- -
  6. SVT | Street View Text Dataset | Chars74K dataset | 带文本的街景 OCR 数据集
  7. 半导体MPW、PCM、WAT、单元库设计
  8. python视频截取
  9. BZOJ1180 [CROATIAN2009]OTOCI
  10. 教徒与非教徒的生存问题(数组解)