珂朵莉树 ODT

struct node
{
	int l , r ; mutable int v ;
	friend bool operator < ( node x , node y ) {
		return x.l < y.l ;
	}
};

m u t a b l e mutable mutable 意为 “可变的”,方便我们在遍历迭代器时可以直接 it->v+= 进行修改

set<node> s ;
auto split( int x ) // 分裂 x-1 与 x 所在段,并返回 x 所在段的迭代器,方便接下来遍历
{
	auto it = s.lower_bound((node){x,0,0}) ;
	if( it != s.end() && it->l == x ) { // x 恰为左端点,不用分裂了
		return it ;
	}
	it -- ;
	if( it->r < x ) return s.end() ; // 没有任何区间包含 x (x=n+1) ,后续不用遍历了 
	int l = it->l , r = it->r , v = it->v ;
	s.erase(it) ;
	s.insert((node){l,x-1,v}) ;
	return s.insert((node){x,r,v}).first ;// 小技巧,直接 .first 返回插入段的迭代器
}

上面 三种情况的讨论一种也不能少!!否则 RE 套餐送上

void assign( int l , int r , int x )
{
	auto itr = split(r+1) , itl = split(l) ;//顺序不能换
	s.erase( itl , itr ) ;
	s.insert((node){l,r,x}) ;
}

注意这里需要先 s p l i t ( r + 1 ) split (r+1) split(r+1) s p l i t ( l ) split (l) split(l) ,这是因为如果反过来, i t l itl itl 会先指向 [ l , > r ] [l,>r] [l,>r] 区间,然后 s p l i t ( r + 1 ) split(r+1) split(r+1) 就把它给删掉了!!

迭代器被删除出 S T L STL STL 容器后,其指代的值仍能访问到 (指针访问) ,但不能再进行任何与 原 S T L STL STL 有关的操作!!

int query( int l , int r , int x )
{
	auto itr = split(r+1) , itl = split(l) ;
	int res = 0 ;
	for( ; itl != itr ; itl ++ ) {
		if( itl->v == x ) res += (itl->r)-(itl->l)+1 ; 
	}
	return res ;
}
int bt[27] ;
void Sort( int l , int r )
{
	auto itr = split(r+1) , itl = split(l) ;
	for(auto it = itl ; it != itr ; it ++ ) {
		bt[it->v] += (it->r)-(it->l)+1 ;
	}
	s.erase( itl , itr ) ;// 先记录信息,后删
	int now = l ;
	for(int i = 0 ; i < 26 ; i ++ ) {
		if( !bt[i] ) continue ;
		s.insert((node){now,now+bt[i]-1,i}) ;
		now += bt[i] ;
		bt[i] = 0 ;
	}
}

(一些拓展操作

总结一下:

珂朵莉树 适合维护 带有区间推平 (assign) 操作的问题

为什么说它是一个暴力数据结构,观察 q u e r y 、 a d d query、add queryadd 等操作本质是 暴力枚举 s e t set set 中连续段,复杂度严重依赖颜色段数

经过一些严谨的证明,可以得到: a s s i g n 、 q u e r y assign、query assignquery 等操作完全随机生成的情况下, s e t set set 中颜色段数总是 O ( l o g n ) O(logn) O(logn)

正因为是暴力,所以能做的操作十分多 甚至频频吊打正解

这使得我们能跨级实现一些令人匪夷所思的 题(骗分

随机数据下十分强力

然而,只用珂朵莉树来维护 a s s i g n assign assign 操作时,复杂度是严格 O ( n l o g n ) O(nlogn) O(nlogn)

Proof :

考虑一次推平操作时,被删除的段分两种:

完全被包含的,删掉就没了,而总段数是 O ( n ) O(n) O(n)

与该段相交的,由于这样的区间最多只有两个,每次推平最多删两段

所以均摊复杂度正确,不依赖于数据随机生成

基于这一点,我们常会用这种 颜色段均摊 的思想维护连续段,再用其它数据结构维护查询操作,以实现正解的复杂度

在这里插入图片描述

  • 13
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值