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