php 匯入 excel 檔案
阿新 • • 發佈:2020-11-30
替罪羊樹
一.是什麼?
這個名字我也不知道是個啥,但是它是一種平衡樹,別的平衡樹都是通過旋轉來維護平衡,而我們的替罪羊樹就不一樣,它就是一個
暴躁老哥!!!
不多廢話,我們來康一康它是如何實現的.
二.為什麼?
讓我們來先看一下它最暴力的操作
顯然,這棵樹不講武德,肯定是要排扁重構的,我們把它變成一條鏈
然後把它從中間拎起來,得到
這樣,這一棵樹就被重構好了.
我們該如何判斷要不要重構呢?,我們要引入一個平衡因子\(\alpha=(0.5,1)\)但是我經常用\(\alpha=0.8\)好像在洛谷上最快
如果一個樹它的子數大小$ \leq siz_{cur} \times \alpha$,那麼這棵樹還懂一點傳統功夫,不用收到制裁,否則就要吧這個子樹暴力重構一下
三.怎麼做?
1.定義變數
struct Scapegoat
{
int Son[2], Exist, Val, Size, Fac;
} node[N + 5];
2.判斷是否需要拍癟
inline bool balance(int x)
{
return (double)node[x].Fac * alpha > (double)max(node[node[x].Son[0]].Fac, node[node[x].Son[1]].Fac);
}
3.新建一個節點
inline void Build(int x) { node[x].Son[0] = node[x].Son[1] = 0, node[x].Size = node[x].Fac = 1; }
4.插入一個節點
inline void Insert(int &x, int val) { if (!x) { x = Void[tot--], node[x].Val = val, node[x].Exist = 1, Build(x); return; } ++node[x].Size, ++node[x].Fac; if (val <= node[x].Val) Insert(node[x].Son[0], val); else Insert(node[x].Son[1], val); }
5.重構!!!!!!
inline void Traversal(int x)
{
if (!x)
return;
Traversal(node[x].Son[0]);
if (node[x].Exist)
cur[++cnt] = x;
else
Void[++tot] = x;
Traversal(node[x].Son[1]);
}
inline void SetUp(int l, int r, int &x)
{
int mid = l + r >> 1;
x = cur[mid];
if (l == r)
{
Build(x);
return;
}
if (l < mid)
SetUp(l, mid - 1, node[x].Son[0]);
else
node[x].Son[0] = 0;
SetUp(mid + 1, r, node[x].Son[1]), PushUp(x);
}
inline void ReBuild(int &x)
{
cnt = 0, Traversal(x);
if (cnt)
SetUp(1, cnt, x);
else
x = 0;
}
inline void check(int x, int val)
{
int s = val <= node[x].Val ? 0 : 1;
while (node[x].Son[s])
{
if (!balance(node[x].Son[s]))
{
ReBuild(node[x].Son[s]);
return;
}
x = node[x].Son[s], s = val <= node[x].Val ? 0 : 1;
}
}
6.其它操作
inline int get_rank(int v)
{
int x = rt, rk = 1;
while (x)
{
if (node[x].Val >= v)
x = node[x].Son[0];
else
rk += node[node[x].Son[0]].Fac + node[x].Exist, x = node[x].Son[1];
}
return rk;
}
inline int get_val(int rk)
{
int x = rt;
while (x)
{
if (node[x].Exist && node[node[x].Son[0]].Fac + 1 == rk)
return node[x].Val;
else if (node[node[x].Son[0]].Fac >= rk)
x = node[x].Son[0];
else
rk -= node[x].Exist + node[node[x].Son[0]].Fac, x = node[x].Son[1];
}
}
inline void Delete(int &x, int rk)
{
if (node[x].Exist && !((node[node[x].Son[0]].Fac + 1) ^ rk))
{
node[x].Exist = 0, --node[x].Fac;
return;
}
--node[x].Fac;
if (node[node[x].Son[0]].Fac + node[x].Exist >= rk)
Delete(node[x].Son[0], rk);
else
Delete(node[x].Son[1], rk - node[x].Exist - node[node[x].Son[0]].Fac);
}
inline void del(int v)
{
Delete(rt, get_rank(v));
if ((double)node[rt].Size * alpha > (double)node[rt].Fac)
ReBuild(rt);
}
四.完結撒花
要完整程式碼的康過來