珂朵莉树(老司机树,ODT,颜色段均摊)

前言

在宿舍里有人说珂朵莉树写起来比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)\) 的迭代器。

代码:

点击查看代码
/* by 01130.hk - online tools website : 01130.hk/zh/requestmethod.html */
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;
}

核心:区间推平

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

点击查看代码
/* by 01130.hk - online tools website : 01130.hk/zh/requestmethod.html */
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\) 排序。
剩余操作和上面差不多。

作者: ltl0825
出处:https://www.cnblogs.com/LTL0825/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须在文章页面给出原文连接,否则保留追究法律责任的权利。
本 PPT 介绍了制药厂房中供配电系统的总体概念与设计要点,内容包括: 洁净厂房的特点及其对供配电系统的特殊要求; 供配电设计的一般原则与依据的国家/行业标准; 从上级电网到工厂变电所、终端配电的总体结构与模块化设计思路; 供配电范围:动力配电、照明、通讯、接地、防雷与消防等; 动力配电中电压等级、接地系统形式(如 TN-S)、负荷等级与可靠性、UPS 配置等; 照明的电源方式、光源选择、安装方式、应急与备用照明要求; 通讯系统、监控系统在生产管理与消防中的作用; 接地与等电位连接、防雷等级与防雷措施; 消防设施及其专用供电(消防泵、排烟风机、消防控制室、应急照明等); 常见高压柜、动力柜、照明箱等配电设备案例及部分设计图纸示意; 公司已完成的典型项目案例。 1. 工程背景与总体框架 所属领域:制药厂房工程的公用工程系统,其中本 PPT 聚焦于供配电系统。 放在整个公用工程中的位置:与给排水、纯化水/注射用水、气体与热力、暖通空调、自动化控制等系统并列。 2. Part 01 供配电概述 2.1 洁净厂房的特点 空间密闭,结构复杂、走向曲折; 单相设备、仪器种类多,工艺设备昂贵、精密; 装修材料与工艺材料种类多,对尘埃、静电等更敏感。 这些特点决定了:供配电系统要安全可靠、减少积尘、便于清洁和维护。 2.2 供配电总则 供配电设计应满足: 可靠、经济、适用; 保障人身与财产安全; 便于安装与维护; 采用技术先进的设备与方案。 2.3 设计依据与规范 引用了大量俄语标准(ГОСТ、СНиП、SanPiN 等)以及国家、行业和地方规范,作为设计的法规基础文件,包括: 电气设备、接线、接地、电气安全; 建筑物电气装置、照明标准; 卫生与安全相关规范等。 3. Part 02 供配电总览 从电源系统整体结构进行总览: 上级:地方电网; 工厂变电所(10kV 配电装置、变压
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值