珂朵莉树
一种特殊的数据结构。
介绍
李欣隆发明。本质上并不是一种树形数据结构,思想是把一个区间按 \(value\) 划分成不少的小区间,然后暴力操作。
显然,这样做的复杂度完全依赖于小区间的多少,所以复杂度需要由区间推平操作保证。
在随机的数据下,可以证明每次的小区间期望有 \(\log_2n\) 个,并且常数极其小。所以常常可以通过 \(10^7\) 的数据。离散化?不存在的。
前置
你需要熟练的操作结构体。
比如你需要学习怎样重载运算符。
bool operator <(const& tt)const{ return ll<tt.ll; }
以及一些 \(set\) 的基本用法,还有迭代器的用法,当然,迭代器可以直接 \(auto.\)
erase(itl,itr);
这行可以直接清空两端点极其之间的所有元素。
\(\texttt{split}\)
设置一个结构体 \(node\),如下所示。
struct node{
int ll,rr;
mutable int val;
node(int L,int R=-1,int V=0): ll(L), rr(R), val(V) {}
bool operator <(const node& tt)const { return ll< tt.ll;}
};
set<node> st;
之后还要考虑 \(split(pos).\)
用处如下:将树中含有下标 \(pos\) 的一段区间分成 \([l,pos-1], [pos,r]\) 两部分,返回一个左边区间的迭代器。
\(\texttt{assign}\)
区间推平操作。\(split\) 之后把中间的 \(erase\) 之后再 \(insert\) 一个较大的区间。
void assign(int ll,int rr,int val){
auto itr=split(rr+1),itl=split(ll);
st.erase(itl,itr);
st.insert(node(ll,rr,val));
}
\(\texttt{Other function}\)
其他的函数大致如下形式:
void func(int ll,int rr){
auto itr=split(rr+1),itl=split(ll);
for(;itl!=itr;++itl) ...
}
比如说区间不同数计数:
int query(int ll,int rr){
unordered_set<int> st2;
auto itr=split(rr+1),itl=split(ll);
for(;itl!=itr;++itl) if(itl->val) st2.insert(itl->val);
return st2.size();
}
纯粹暴力。

浙公网安备 33010602011771号