首页 > 其他分享 >珂朵莉树(ODT)

珂朵莉树(ODT)

时间:2024-10-11 16:50:16浏览次数:4  
标签:node Chtholly insert int ODT pos 朵莉树 split

ODT:优雅的暴力

核心思想:set 存储一段权值相同的区间以及权值,区间赋值暴力推平。

要求:数据随机,有区间赋值操作,此时复杂度趋近于 \(O(m \log n)\)。

区间的定义:

struct node{
	int l,r;//左,右
	mutable int v;//权值
	bool operator <(const node &n)const{//按左端点从小到大排序
		return l<n.l;
	}
};
using IT=set<node>::iterator;//set迭代器
set<node> Chtholly;

split 函数:分离出一段以 pos 为左端点的区间。

IT split(int pos){
	IT it=Chtholly.lower_bound({pos,-1,0});//二分查找以 pos 为左端点的区间
	if(it!=Chtholly.end()&&it->l==pos)//找到返回迭代器
		return it;
	it--;//否则肯定在上一个(lower_bound:>=)
	int l=it->l,r=it->r,v=it->v;
	Chtholly.erase(it);//删掉 [l,r],分成 [l,pos-1] 和 [pos,r]
	Chtholly.insert((node){l,pos-1,v});
	return Chtholly.insert((node){pos,r,v}).first;//返回 [pos,r]
}

assign 函数:区间推平操作(区间赋值):

void assign(int l,int r,int v){
	IT R=split(r+1),L=split(l);//split 迭代器
	//为什么要 split(r+1) 而不是 split(r)
	//我们要删除的区间是 [l,r] 这一段
	//erase 函数删除的是左闭右开的区间,即 erase(begin,end) 不删 end 
	//如果 split(r) 就会少删 r 
	Chtholly.erase(L,R);//删
	Chtholly.insert((node){l,r,v});//将这一段区间的权值改成v
}

以上就是珂朵莉树的基本操作。

模板题:CF915E

维护一个变量 sum 代表工作日个数,assign 操作时暴力枚举中间的区间更新 sum 即可。(要快读快写)

vjudge 上测 749ms 快到飞起。太优雅了

#include<bits/stdc++.h>
using namespace std;
struct node{
	int l,r;
	mutable int v;
	bool operator <(const node &n)const{
		return l<n.l;
	}
};
using IT=set<node>::iterator;
set<node> Chtholly;
int n,q;
int l,r,k,sum;
IT split(int pos){
	IT it=Chtholly.lower_bound({pos,-1,0});
	if(it!=Chtholly.end()&&it->l==pos)
		return it;
	it--;
	int l=it->l,r=it->r,v=it->v;
	Chtholly.erase(it);
	Chtholly.insert((node){l,pos-1,v});
	return Chtholly.insert((node){pos,r,v}).first;
}
void assign(int l,int r,int v){
	IT R=split(r+1),L=split(l);
	for(IT it=L;it!=R;it++)//暴力枚举统计
		sum-=(it->r-it->l+1)*(it->v-v);
	Chtholly.erase(L,R);
	Chtholly.insert((node){l,r,v});
}
template<typename T>
inline void read(T &x){
    char c;
    x=0;
    int fu=1;
    c=getchar();
    while(c>'9'||c<'0'){
        if(c=='-')fu=-1;
        c=getchar();
    }
    while(c<='9'&&c>='0'){
        x=(x<<3)+(x<<1)+c-'0';
        c=getchar();
    }
    x*=fu;
}
template<typename T>
inline void print(T x){
    if(x<0){
        putchar('-');
        x=-x;
    }
    if(x>9)print(x/10);
    putchar(x%10+'0');
}
int main(){
	read(n);read(q);
	sum=n;
	Chtholly.insert((node){1,n,1});
	while(q--){
		read(l);read(r);read(k);
		assign(l,r,k-1);
		print(sum);printf("\n");
	}
	return 0;
}

标签:node,Chtholly,insert,int,ODT,pos,朵莉树,split
From: https://www.cnblogs.com/z-Sqrt-xf/p/18458830/Chtholly-Tree

相关文章

  • 珂朵莉树(ODT)学习笔记
    对一个序列进行推平和查询等操作,我们难免会有过这样的想法:只维护连续段即可。但是这只是比较优的暴力,精心构造的数据可以轻松卡掉。事实上,在随机数据下,这样的算法的时间复杂度是\(\mathcal{O}(n\logn)\),这就是颜色段均摊理论,证明不会。根据这个理论产生了珂朵莉树,它可以维护区......
  • 珂朵莉树(ODT)
    前言主要是一种暴力思想。。。本文来自wiki与洛谷题解的整合。应用主要是应付随机数据(区间操作)实现有几个核心操作。set实现方法定义structnode{ inttl,r;//intt:longlong mutableinttv; node(constintt&ll,constintt&rr,constintt&vv):l(ll),r(rr),v......
  • 珂朵莉树
    吾日三省吾身:末日时在干什么?有没有空?可以来拯救一下吗?算法思想非常简单:就是暴力。对于数据结构题,我们有这样一种思路去维护:对于一个数列,我们把不同的数字看成不同的颜色段,然后对每个颜色段进行暴力操作,可以有效降低时间复杂度。但这种暴力是很好卡掉的,只需让颜色段尽可能多,算法......
  • 珂朵莉树
    经典题(珂朵莉树的诞生):https://www.luogu.com.cn/problem/CF896C参考:https://www.luogu.com.cn/article/yfcae6d6不用知道它的具体复杂度,主要是学习如何实现。珂朵莉树(ChthollyTree),又名老司机树ODT(OldDriverTree)。splitpos区间分割操作,也就是将包含pos的区间分割为两端......
  • 题解:P11007 『STA - R7』Odtlcsu
    评价:简单构造。思路注意题目中的“如果有多解输出任意一种即可”。由于\(a\)与\(a^{2}\)的奇偶性必定是一致的,所以我们可以将情况分为两种。当\(x\)与\(y\)奇偶性不一致时,但由于\(a\)与\(a^{2}\)的奇偶性必定是一致的,所以始终无法构造出正确的序列。但注意题目......
  • 珂朵莉树/颜色段均摊学习笔记
    珂朵莉树是基于set的数据结构,与线段树、平衡树等树形结构类似,珂朵莉树是用来解决区间问题的很暴力的树形结构该数据结构支持区间推平,即将区间\([l,r]\)赋值为同一个值1.前置知识setset本质是平衡树,所以不会出现重复的元素且会自动排序,部分函数:set<Node>t;//定......
  • 【学习笔记】珂朵莉树
    前言珂朵莉树(ChthollyTree),又名老司机树(OldDriverTree),起源自CF896CWillem,ChthollyandSeniorious。严格来说,珂朵莉树这种想法是基于数据随机的颜色段均摊,而不是一种数据结构,可作为一些题目的暴力做法(因此原题被分到了暴力数据结构的标签),在随机数据下一般效率较高。基......
  • [CF1172E] Nauuo and ODT
    [CF1172E]NauuoandODT首先考虑单次询问,将每个颜色拉出来,求解有多少条路径至少包含一个给定点。这就是维护所有黑色连通块的大小平方和。我们每一次删掉一个点就等价于将所有和他相连的点删掉,这样一定会T。可以使用类似CF487ETourists的套路,将其父亲—儿子化,如果一个点......
  • 洛谷 CF896C Willem, Chtholly and Seniorious之珂朵莉树板子
    洛谷CF896C题解传送锚点摸鱼环节Willem,ChthollyandSeniorious题面翻译【题面】请你写一种奇怪的数据结构,支持:\(1\)\(l\)\(r\)\(x\):将\([l,r]\)区间所有数加上\(x\)\(2\)\(l\)\(r\)\(x\):将\([l,r]\)区间所有数改成\(x\)\(3\)\(l\)\(r\)\(x\):输出将\(......
  • 【模板】珂朵莉树
    这是即将推送到OI-wiki的,对于原OI-wiki珂朵莉树页面的重构。作者是我。感谢上一位维护这玩意的人。简介珂朵莉树(ChthollyTree),又名老司机树ODT(OldDriverTree)。起源自CF896C。这个名称指代的是一种“使用平衡树(std::set、std::map等)或链表(std::list、手写链表等)维护颜......