騙分導論--ODT珂朵莉樹
阿新 • • 發佈:2018-12-15
珂朵莉樹の由來
由於其騙分暴力的非正統演算法思想 雖然很多時候在隨機資料下跑時不錯 但切記這只是騙分暴力,時間複雜度上並不正確
什麼時候用珂朵莉樹
珂朵莉樹一般用來解決本來應當由線段樹解決的區間類問題
而使得珂朵莉樹暴力艹標程的關鍵是assign區間推平操作 也就是題目中必須有區間賦值操作,而且資料純隨機的情況下才有複雜度保證
珂朵莉樹–初始化
一般珂朵莉樹選擇使用 set 維護數列 set中每個結點維護三個值,意為內的值都為 也就是每個節點儲存一段連續的值相同的區間
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;
需要注意的是 沒有它對的修飾,在接下來add函式裡導致CE。
接下來為方便有關迭代器的操作,我們做一個巨集定義
#define IT set<node>::iterator
珂朵莉樹–分裂Split
操作是指將原來含有pos位置的節點分成兩部分和 並返回分裂後以為左端點的結點的迭代器
IT split(int pos)
{
IT it=st.lower_bound(node(pos));//二分找到第一個左端點不小於pos的區間
if(it!=st.end()&&it->ll==pos) return it;//pos本身就是某個區間的左端點,不用分裂
--it;//否則上一個區間才是包含pos的區間
int ll=it->ll,rr=it->rr,val=it->val;
st.erase(it);//刪除原結點
st.insert(node(ll,pos-1,val));
return st.insert(node(pos,rr,val)).first;//這裡.first返回的是迭代器
}
珂朵莉樹–區間賦值Assign
珂朵莉樹就是靠這個東西維持其不正確的複雜度的
void assign(int ll,int rr,int val)
{
IT itr=split(rr+1),itl=split(ll);
st.erase(itl,itr);
st.insert(node(ll,rr,val));
}
分裂出需要的區間,刪除後重新插入一個新的 注意分裂出區間時要先分裂右端點,在分裂左端點
方法可以刪除迭代器描述的區間,注意左閉右開
void erase (iterator first, iterator last)
在資料純隨機的情況下,可以證明每次的區間長度期望為
於是規模迅速下降,隨後達到接近的玄學非正確複雜度
珂朵莉樹–其他暴力操作
其他操作真的就是規規矩矩的純暴力 直接取出對應區間,暴力對每一個進行操作
一般就是長這樣
void fun(int ll,int rr)
{
IT itr=split(rr+1),itl=split(ll);
for(;itl!=itr;++itl)
{
//...
}
}
煮個栗子–區間求和
int qsum(int ll,int rr)
{
int res=0;
IT itr=split(rr+1),itl=split(ll);
for(;itl!=itr;++itl) res+=(itl->rr-itl->ll+1)*itl->val;//注意乘(itl->rr-itl->ll+1)
return res;
}
再煮個複雜點的栗子–區間Kth
也是一樣的暴力
#define pir pair<int,int>//前一個記錄值,後一個記錄出現次數
int kth(int ll,int rr,int k)
{
vector<pir> vec;
IT itr=split(rr+1),itl=split(ll);
for(;itl!=itr;++itl)
vec.push_back( pir(itl->val,itl->rr-itl->ll+1) );
sort(vec.begin(),vec.end());//全部存下來排序就好
for(vector<pir>::iterator it=vec.begin();it!=vec.end();++it)
{
k-=it->second;
if(k<=0) return it->first;
}
return -1;
}
再次提醒
不管珂朵莉樹才實際中再怎麼優秀,那都只是資料隨機的結果 說到底只是暴力騙分手段 儘管可以用ODT AC很多題,但改變不了時間複雜度是非正確的的事實
建議平時的練習中少用,因為這樣會忽略了題目本身正解的精髓 考場上對題目沒有思路倒是一個很好的騙分手段