珂朵莉树(ODT)

珂朵莉树

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

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

区间的定义:

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;
}
posted @   imzfx_Square  阅读(21)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示