当前位置: 首页 > news >正文

ODT/珂朵莉树 入门

主打一个看到别人学什么我学什么,反正什么也不会。

什么是 ODT

是一种数据结构

类比线段树的话,他的每一条线段(一个基本单位)记录了相同 "颜色" 的东西的信息
使用一个结构体的 \(set\),记录 区间 \([l,r]\) 的信息都为 \(k\)

时间复杂度

随机数据可能是 \(O(n)\) 的,一般可以认为是 \(O(nlogn)\) ,但有时也可以卡到 \(nlog^2n\)
不知道,差不多用就是了

解决什么问题

根据其特性,可以解决区间 \(k\) 大,区间元素幂的和...
还有什么做到了再说.....

ODT 怎么维护

核心是 Split 操作

对于一个 \(pos\) 的修改,找到覆盖 \(pos\) 的区间 \([l,r]\) ,将他分开变成 \([l,pos-1],[pos,r]\) ,然后返回 \([pos,r]\) 区间的迭代器

区间修改操作

\([l,r]\) 赋值为 \(x\)\(split(r+1)\) ,再 \(split(l)\)
原因就是 \(split(l)\) 会影响后面的值
然后删掉两个迭代器中间的信息,全部变成一个 \([l,r],x\)

所以我们得到模版代码,有一些不常用的东西

模版

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define IT set<node>::iterator
struct node{int l,r;mutable ll v;//mutable就是你在用迭代器访问的时候也可以直接赋值 bool operator < (const node &a)const {return l<a.l;}
};
set<node> s;
IT split(int pos){IT it=s.lower_bound(node{pos,0,0});if(it!=s.end()&&is->l==pos)return it;it--;if((it->r)<pos)return s.end();//写指针注意加括号int l=it->l,r=it->r;ll v=it->v;s.erase(it);s.insert(node{l,pos-1,v});return s.insert(node{pos,r,v}).first;//set.insert返回一个 pair :first指向插入后该元素的迭代器,second则为bool表示插入是否成功。 
}
void upd(int l,int r,int x){IT itr=split(r+1);//因为我们要拆出 $[l,r]$ 而split会拆出 [l,pos-1]所以应该是r+1IT itl=split(l);s.erase(itl,itr);//表示删除两迭代器中间的所有元素s.insert(node{l,r,x}); 
} 

例题

对于 \(ODT\) 的题,答案的维护一般就在 \(upd\) 函数里,没有固定模版

CF915E

非工作日为 \(0\) ,工作日为 \(1\) ,就是维护全局和,那就每次减去旧区间和加上新的

#include<bits/stdc++.h>
using namespace std;
const int N=3e5+10;
#define ll long long
#define IT set<node>::iterator
int n,q;
struct node{int l,r;mutable ll v;bool operator <  (const node &a)const {return l<a.l;}
};
set<node>s;
IT split(int pos){IT it=s.lower_bound(node{pos,0,0});if(it!=s.end()&&it->l==pos)return it;it--;if(it->r<pos)return s.end();int l=it->l,r=it->r;ll v=it->v;s.erase(it);s.insert(node{l,pos-1,v});return s.insert(node{pos,r,v}).first;
}
ll ans=0;
void upd(int l,int r,int x){IT itr=split(r+1),itl=split(l);for(IT it=itl;it!=itr;it++)ans-=1ll*(it->v)*((it->r)-(it->l)+1);ans+=1ll*(r-l+1)*x;s.erase(itl,itr);s.insert(node{l,r,x}); 
}
signed main(){ios::sync_with_stdio(false);cin.tie(0),cout.tie(0);cin>>n>>q;ans=n;s.insert(node{1,n,1});while(q--){int l,r,x;cin>>l>>r>>x;upd(l,r,x-1);cout<<ans<<"\n";}return 0;
}
http://www.hskmm.com/?act=detail&tid=10219

相关文章:

  • 在AI技术快速实现功能的时代,挖掘新需求成为关键突破点——某知名游戏资源分析工具需求洞察
  • 蜜罐
  • 【光照】[漫反射]UnityURP兰伯特有光照衰减吗?
  • prenotami.esteri.it 意大利签证预约error
  • reLeetCode 热题 100- 15. 三数之和 - MKT
  • XXL-TOOL v2.1.0 发布 | Java工具类库
  • Python-Pathlib库
  • 反省
  • [Nacos/Docker/MCP] Nacos 3.x : 为 AI MCP 而生
  • 牛客周赛 Round 108 CDEF题解
  • Redis的使用问题
  • AIGC拾遗:Flash Attention
  • 深度好文-风雨飘摇信竞路
  • Python-CSV库
  • C++小白修仙记_LeetCode刷题_位运算
  • C++小白修仙记_LeetCode刷题_双指针
  • 前路漫漫亦灿灿 往事堪堪亦澜澜
  • 使用uv和pycharm搭建python开发环境
  • lc1032-字符流
  • C++小白修仙记_LeetCode刷题_哈希表
  • 【F#学习】字符串String
  • 现代汽车前瞻杯2025牛客暑期多校训练营3
  • 实用指南:多技术融合提升环境生态水文、土地土壤、农业大气等领域的数据分析与项目科研水平
  • 【F#学习】“变量”?绑定!
  • 2023 CCPC 深圳 F
  • 完整教程:【算法】双指针(三)[快慢指针]-快乐数
  • 9.19做题资料:哈希表查找时间复杂度分析
  • CF2143F Increasing Xor
  • 提到链接,你能想到什么
  • 实用指南:容器逃逸漏洞