前言

在宿舍里有人说珂朵莉树写起来比shi山线段树方便多了。

正文

珂朵莉树,又名老司机树,颜色段均摊,ODT。

可以在数据完全随机化的情况下较快的完成一些操作(所以容易被卡)。

珂朵莉树其实形态并不像树,基于set或是链表,是一种很暴力的数据结构。


先来看一到例题(珂朵莉树起源题)

CF896C

题目大意:

有一个序列,你需要编写程序支持以下操作:

1 l r x :将[l,r]区间所有数加上x

2 l r x :将[l,r]区间所有数改成x

3 l r x :输出将[l,r] 区间从小到大排序后的第x个数是的多少

4 l r x y :输出[l,r] 区间每个数字的x次方的和模y的值

天哪线段树直接报废

进入正题:

珂朵莉树的每个节点由一个三元组组成 \((l,r,val)\) 表示从 \(l \sim r\) 这段区间中的值都是 \(val\)。

例如:

\(1,1,3,3,3,3,2,2,2,1,1,1\),构造时长这样:

\((1,2,1),(3,6,3),(7,9,2),(10,12,1)\)

珂朵莉树中的点按 \(l\) 排序。

操作1:

例如我想让 \(2 \sim 11\) 中的数 \(+1\)

但是:这并不是几个整个节点,所以我们需要拆点。

核心:区间分割

现在我们可以将 \((1,2,1)\) 变为 \((1,1,1)\) 和 \((2,2,1)\),将 \((10,12,1)\) 变为 \((10,11,1)\) 和 \((12,12,1)\)。

接着我们就可以将 \((2,2,1),(3,6,3),(7,9,2),(10,11,1)\) 中的 \(val\) 都 \(+1\)

所以我们将 split(x) 定义为找到 \(x\) 所在的区间 \((l,r,val)\) 将其分为 \((l,x-1,val)\) 和 \((x,r,val)\) 并返回 \((x,r,val)\) 的迭代器。

代码:

点击查看代码
struct node{
int l,r;
mutable int v;//mutalbe 可变,可以修改此值,一定要加,不然无法修改v
bool operator < (const node&W)const
{
return l<W.l;
}
};
set<node> tree;
auto split(int x)
{
auto it=tree.lower_bound({x,0,0});
if(it!=tree.end()&&it->l == x)
{
return it;
}
it--;
int l=it->l,r=it->r,v=it->v;
tree.erase(it);
tree.insert({l,x-1,v});
return tree.insert({x,r,v}).first;
}

核心:区间推平

这个很好办,直接看代码:

点击查看代码
void assign(int l,int r,int v)
{
auto itr=split(r+1),itl=split(l);
tree.erase(itl,itr);//erase 左闭又开
tree.insert({l,r,v});
}

注意:

一定要先进行split(r+1)在进行split(l) 否则会RE

例如 \((1,4,1),l=1,r=2\)

若先进行split(l):

itl=(1,4,1)的迭代器

split(r+1)

此时 \((1,4,1)\) 会被分裂成 \((1,2,1)\) 和 \((3,4,1)\)

此时的 \((1,4,1)\) 已经被删掉了,所以 \(itl\) 就是一个野指针,遍历时会出问题。

add操作

解决了问题,add操作就很好写。

点击查看代码
void add(int l,int r,int v)
{
auto itr=split(r+1),itl=split(l+1);
for(auto it=itl;it!=itr;it++)
{
it->v+=v;
}
}

别的也是类似于这样。

珂朵莉树的总代码(核心部分)

点击查看代码
struct node{
int l,r;
mutable int v;//mutalbe 可变,可以修改此值
bool operator < (const node&W)const
{
return l<W.l;
}
};
set<node> tree;
auto split(int x)
{
auto it=tree.lower_bound({x,0,0});
if(it!=tree.end()&&it->l == x)
{
return it;
}
it--;
int l=it->l,r=it->r,v=it->v;
tree.erase(it);
tree.insert({l,x-1,v});
return tree.insert({x,r,v}).first;
}
void assign(int l,int r,int v)
{
auto itr=split(r+1),itl=split(l);
tree.erase(itl,itr);
tree.insert({l,r,v});
}
void build(int l,int r,int *a)
{
tree.clear();
int pos=l;
for(int i=l+1;i<=r;i++)
{
if(a[pos]!=a[i])
{
tree.insert({pos,i-1,a[pos]});
pos=i;
}
}
tree.insert({pos,r,a[pos]});
}

变种

珂朵莉树其实也可以建立在值域上(类似于权值线段树)

此时的node变为:

\((val,cnt)\) 表示 \(val\) 出现了 \(cnt\) 次,按 \(val\) 排序。

剩余操作和上面差不多。

珂朵莉树(老司机树,ODT,颜色段均摊)的更多相关文章

  1. 牛客练习赛7 E 珂朵莉的数列(树状数组+爆long long解决方法)

    https://www.nowcoder.com/acm/contest/38/E 题意: 思路: 树状数组维护.从大佬那里学习了如何处理爆long long的方法. #include<iost ...

  2. 【学习笔记】珂朵莉树(ODT)

    珂朵莉树 \(\tt 0x00\) 起源 起源于 CodeForces 的一题 CF896C,当时出题人提供了这种做法,在随机数据下均摊复杂度比较优秀. 正统名字好像叫颜色段均摊,由于题目也得名于 \ ...

  3. 「学习笔记」珂朵莉树 ODT

    珂朵莉树,也叫ODT(Old Driver Tree 老司机树) 从前有一天,珂朵莉出现了... 然后有一天,珂朵莉树出现了... 看看图片的地址 Codeforces可还行) 没错,珂朵莉树来自Co ...

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

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

  5. 珂朵莉树(ODT)笔记

    珂朵莉树,又叫老司机树($Old\, Driver \, Tree$) 是一种暴力出奇迹,就怕数据不随机的数据结构. 适用 需要用线段树维护一些区间修改的信息…… 像是区间赋值(主要),区间加…… 原 ...

  6. [数据结构]ODT(珂朵莉树)实现及其应用,带图

    [数据结构]ODT(珂朵莉树)实现及其应用,带图 本文只发布于博客园,其他地方若出现本文均是盗版 算法引入 需要一种这样的数据结构,需要支持区间的修改,区间不同值的分别操作. 一般的,我们会想到用线段 ...

  7. 洛谷AT2342 Train Service Planning(思维,动态规划,珂朵莉树)

    洛谷题目传送门 神仙思维题还是要写点东西才好. 建立数学模型 这种很抽象的东西没有式子描述一下显然是下不了手的. 因为任何位置都以\(k\)为周期,所以我们只用关心一个周期,也就是以下数都在膜\(k\ ...

  8. 洛谷P4344 [SHOI2015]脑洞治疗仪(珂朵莉树)

    传送门 看到区间推倒……推平就想到珂朵莉树 挖脑洞直接assign,填坑先数一遍再assign再暴力填,数数的话暴力数 //minamoto #include<iostream> #inc ...

  9. 洛谷P2787 语文1(chin1)- 理理思维(珂朵莉树)

    传送门 一看到区间推倒……推平操作就想到珂朵莉树 区间推平直接assign,查询暴力,排序的话开一个桶统计,然后一个字母一个字母加就好了 开桶统计的时候忘了保存原来的左指针然后挂了233 //mina ...

  10. 洛谷P2082 区间覆盖(加强版)(珂朵莉树)

    传送门 虽然是黄题而且还是一波离散就能解决的东西 然而珂朵莉树还是很好用 相当于一开始区间全为0,然后每一次区间赋值,问最后总权值 珂朵莉树搞一搞就好了 //minamoto #include< ...

随机推荐

  1. [RCTF2015]EasySQL 报错注入与二次注入

    [RCTF2015]EasySQL 报错注入与二次注入 二次注入,可以概括为以下两步: 第一步:插入恶意数据 进行数据库插入数据时,对其中的特殊字符进行了转义处理,在写入数据库的时候又保留了原来的数据 ...

  2. IntelliJ IDEA 中,项目文件右键菜单没有svn选项解决办法

    问题描述 欲在IntelliJ IDEA中提交文件至SVN,但是在项目文件上点击右键时,发现右键菜单中没有Subversion的选项,正常情况下是要有的,如下图所示: 图0 解决办法 点击菜单:VCS ...

  3. 详解鸿蒙开发如何上传三方库到ohpm仓库

    前两天幽蓝君在ohpm仓库上传了自己的第一个三方库,完整体验了一下ohpm的上传流程,感觉还是比较繁琐的,所以把上传流程和一些注意事项分享给大家. 先介绍一下怎么开发一个三方库,在项目名称右键,新建M ...

  4. CSP-S 2020模拟训练题1-信友队T4 二维码

    题意简述 有一个初始全白的\(n*m\)大小的二维网格,每次可以选择一行或一列染全白或全黑.问可以通过任意次该操作得到多少不同的网格.答案对998244353取模. 分析 不难发现,无论怎么染色,都不 ...

  5. Re:prime 关于质数的算法

    Re:prime 关于质数的所有算法 绪言 所有代码若无说明,均采用快读模板 关于质数,无非就两大类: 判断一个数字是不是质数 找出[1,n]中所有的质数 先讲1: Judge 判断x是不是质数 根据 ...

  6. 在MySQL中悲观锁及乐观锁的应用

    本文由 ChatMoney团队出品 在数据库管理系统中,锁机制是保证数据一致性和并发控制的重要手段.MySQL,作为广泛使用的数据库系统之一,提供了多种锁策略来处理并发访问时可能引发的数据不一致性问题 ...

  7. 亚太唯一!阿里云Serverless计算产品进入Forrester领导者象限

    近日,全球权威咨询机构Forrester发布Serverless开发平台评估报告<Forrester Wave: Serverless Development Platforms, Q2 202 ...

  8. 基于开源流批一体数据同步引擎ChunJun数据还原—DDL解析模块的实战分享

    原文链接:基于开源流批一体数据同步引擎ChunJun数据还原-DDL解析模块的实战分享 课件获取:关注公众号** "数栈研习社",后台私信 "ChunJun"* ...

  9. SQL Server 重复记录,查询,筛查,指定保留

    Select * From 表 x Where 重复字段 In (Select 重复字段 From 表 Group By 重复字段 Having Count(*)>1) Order BY 重复字 ...

  10. java.lang.IllegalArgumentException: java.lang.ClassCastException

    使用反射回调时出现了异常,这里做一下记录 Method method = instance.getClass().getMethod(setter, filedClazz);method.invoke ...