最強平衡樹——Treap[以我的最弱擊敗你的最強]
僕の最弱を以て,君の最強を打ち破る。!!——Treap
本人蒟蒻,在平衡樹坑中深陷數年。為了早日逃離此天坑,特作此文。
什麼是平衡樹?度娘傳送門
什麼是treap?ACdreamers%%%
注:本篇所有程式碼都在片尾!!(醒目)
CMP
那麼瞭解了這些,我們先列出一個list
NAME | 優勢 | 劣勢 |
---|---|---|
splay | LCT,序列之王 | 常數大,程式碼量稍大 |
RBT | 自適應深度平衡樹,速度在同類BST中遙遙領先 | 程式碼量大 |
SBT | 程式碼簡短,速度快,(退化版很好寫) | 功能平平,(退化版會被人字梯資料卡掉) |
大體上來說,treap的敵人多為這三類。我們逆著證明treap是最強的。
TREAP VS SBT
就以常數來說,sbt與treap的常數皆為12左右,當然以數學證明的
inline int random(){
static int seed=703; //seed可以隨便取
return seed=int(seed*48271LL%2147483647);
}
以數學的方法快速取得rand值 相關連結
這樣一來比較不加讀優,sbt為260ms+,treap為360ms+,速度已經很相近了。。。並且由於treap比sbt多一個rd陣列存rand值,能有70%左右的速度已經非常可觀了,但這不是重點。
Treap真正能夠超越sbt的在於可以快速分裂與合併,這是sbt很難做到的,而且一旦去做,就必定會加入Father指標,這樣會拖慢sbt旋轉的速度。
詳見程式碼 HERE
TREAP VS RBT
這可能是treap最大的敵人,速度足夠碾壓剛剛還得瑟的SBT(cqf的論文中雖然號稱比AVL快[實際情況我還沒有試過],但是不敢說比RBT快),STL中set,map這些常用型別的底層實現方式。
這就是讓人恐懼並無法自拔(?)的RBT(紅黑樹)!!
那麼這麼強大的平衡樹,為什麼區區一介treap敢於挑戰?
在與。。。還記得我對RBT的描述嗎?深度平衡樹
那麼就用你的優勢成為你失敗的伏筆!!!
引出重量級
重量平衡樹與字尾平衡樹 麗潔姐的論文
可以發現能夠支撐起平衡樹向字串領域進軍的,就是treap!!
複雜度在加入了一個類似於線段樹的結構後並沒有改變
綜上,treap可以完成許多深度平衡樹(AVL、RBT)(SBT算什麼?)無法做到的效果。
TREAP VS SPLAY
首先分裂與合併已經在討論sbt時解決了,再者splay的常數又是在平衡數中排得上名號的(大根堆),單旋spaly直接被鏈式資料卡死,所以splay只有在序列與LCT上稱王稱霸。LCT有關
但真的是這樣嗎?
談談Treap與LCT,既然都能不旋轉來分裂合併了,那麼LCT自然是手到擒來。LCT例子
CDQZ本部的幾個大神就是LCT只打treap。
所以splay能得瑟的就是序列之王這個名號了!
光速打臉 NOI2005 維護數列
呵呵,雖然分裂合併式的Treap,速度慢,但是程式碼很好寫,畢竟靠隨機值無腦合併分裂啊。
結論(彩蛋?)
的確,treap在速度上輸給了sbt、rbt(遠遠地),程式碼量上也僅僅與sbt持平(基礎部分不到40行),分裂合併的常數值也比splay大。。
(觀眾:好像一無是處耶?)
但是treap反向證明了它自己可以做到那麼多不同平衡樹自己獨具特點的功能,就好比金庸集各家之大成,雖未超越,但單單地將其聚合起來也足以稱王了。
從重量平衡引申出的字尾平衡樹,非旋轉式引出分裂與合併,treap很弱,因為它不完整(從定義上就不完整),但也正是如此他對於OIer來說不是如RBT般的神,splay般的功能強大,sbt般的簡潔飛速,所以它需要成長,對於沒一點常數的爭取,對於自身結構的改變,以及。。。。。本文最後的彩蛋!!
可持久化平衡樹
這是多少OIer在可持久化treap發明前學平衡樹的心結,那麼強大的平衡樹為什麼沒有能簡單可持久化的方式呢?直到可持久化treap橫空出世,震驚全球(誇張。),多少代OIer的願望通過treap殘缺的美在此得以實現。
code
普普通通的treap——rand()優化後
bzoj3224 普通平衡樹
#include<iostream>
#include<cstdio>
#include<cstdlib>
using namespace std;
struct data{
int l,r,v,size,rnd,w;
}tr[100005];
int n,size,root,ans;
inline int randad(){
static int seed=703; //seed可以隨便取
return seed=int(seed*48271LL%2147483647);
}
void update(int k)//更新結點資訊
{
tr[k].size=tr[tr[k].l].size+tr[tr[k].r].size+tr[k].w;
}
void rturn(int &k)
{
int t=tr[k].l;tr[k].l=tr[t].r;tr[t].r=k;
tr[t].size=tr[k].size;update(k);k=t;
}
void lturn(int &k)
{
int t=tr[k].r;tr[k].r=tr[t].l;tr[t].l=k;
tr[t].size=tr[k].size;update(k);k=t;
}
void insert(int &k,int x)
{
if(k==0)
{
size++;k=size;
tr[k].size=tr[k].w=1;tr[k].v=x;tr[k].rnd=randad();
return;
}
tr[k].size++;
if(tr[k].v==x)tr[k].w++;
else if(x>tr[k].v)
{
insert(tr[k].r,x);
if(tr[tr[k].r].rnd<tr[k].rnd)lturn(k);
}
else
{
insert(tr[k].l,x);
if(tr[tr[k].l].rnd<tr[k].rnd)rturn(k);
}
}
void del(int &k,int x)
{
if(k==0)return;
if(tr[k].v==x)
{
if(tr[k].w>1)
{
tr[k].w--;tr[k].size--;return;
}
if(tr[k].l*tr[k].r==0)k=tr[k].l+tr[k].r;
else if(tr[tr[k].l].rnd<tr[tr[k].r].rnd)
rturn(k),del(k,x);
else lturn(k),del(k,x);
}
else if(x>tr[k].v)
tr[k].size--,del(tr[k].r,x);
else tr[k].size--,del(tr[k].l,x);
}
int query_rank(int k,int x)
{
if(k==0)return 0;
if(tr[k].v==x)return tr[tr[k].l].size+1;
else if(x>tr[k].v)
return tr[tr[k].l].size+tr[k].w+query_rank(tr[k].r,x);
else return query_rank(tr[k].l,x);
}
int query_num(int k,int x)
{
if(k==0)return 0;
if(x<=tr[tr[k].l].size)
return query_num(tr[k].l,x);
else if(x>tr[tr[k].l].size+tr[k].w)
return query_num(tr[k].r,x-tr[tr[k].l].size-tr[k].w);
else return tr[k].v;
}
void query_pro(int k,int x)
{
if(k==0)return;
if(tr[k].v<x)
{
ans=k;query_pro(tr[k].r,x);
}
else query_pro(tr[k].l,x);
}
void query_sub(int k,int x)
{
if(k==0)return;
if(tr[k].v>x)
{
ans=k;query_sub(tr[k].l,x);
}
else query_sub(tr[k].r,x);
}
int main()
{
scanf("%d",&n);
int opt,x;
for(int i=1;i<=n;i++)
{
scanf("%d%d",&opt,&x);
switch(opt)
{
case 1:insert(root,x);break;
case 2:del(root,x);break;
case 3:printf("%d\n",query_rank(root,x));break;
case 4:printf("%d\n",query_num(root,x));break;
case 5:ans=0;query_pro(root,x);printf("%d\n",tr[ans].v);break;
case 6:ans=0;query_sub(root,x);printf("%d\n",tr[ans].v);break;
}
}
return 0;
}
序列treap
BZOJ1500 維護數列
#define INF 2000000000
#define N 500010
struct Node;
Node *null,*root;
struct Node
{
int w,sz,val,sum,ls,rs,ss,lzy1,lzy2;
Node *lft,*rht;
void split(int,Node*&,Node*&);
void same(int v)
{
if(this==null) return;
lzy2=val=v;
sum=v*sz;
ls=rs=ss=max(sum,v);
}
void rev()
{
if(this==null) return;
lzy1^=1;
swap(lft,rht);
swap(ls,rs);
}
Node *pushup()
{
sz=lft->sz+1+rht->sz;
sum=lft->sum+val+rht->sum;
ls=max(lft->ls,lft->sum+val+max(0,rht->ls));
rs=max(rht->rs,rht->sum+val+max(0,lft->rs));
ss=max(0,lft->rs)+val+max(0,rht->ls);
ss=max(ss,max(lft->ss,rht->ss));
return this;
}
Node *pushdown()
{
if(lzy1)
{
lft->rev();
rht->rev();
lzy1=0;
}
if(lzy2!=-INF)
{
lft->same(lzy2);
rht->same(lzy2);
lzy2=-INF;
}
return this;
}
};
Node *merge(Node *p,Node *q)
{
if(p==null) return q;
if(q==null) return p;
if(p->w<q->w)
{
p->pushdown();
p->rht=merge(p->rht,q);
return p->pushup();
}
q->pushdown();
q->lft=merge(p,q->lft);
return q->pushup();
}
void Node::split(int need,Node *&p,Node *&q)
{
if(this==null)
{
p=q=null;
return;
}
pushdown();
if(lft->sz>=need)
{
lft->split(need,p,q);
lft=null;
pushup();
q=merge(q,this);
return;
}
rht->split(need-(lft->sz+1),p,q);
rht=null;
pushup();
p=merge(this,p);
return;
}
Node data[N],*pool[N];
int top,cnt;
Node* newnode(int c)
{
Node *x;
if(top) x=pool[top--];
else x=&data[cnt++];
x->lft=x->rht=null;
x->sz=1; x->lzy1=0; x->lzy2=-INF;
x->val=x->sum=x->ls=x->rs=x->ss=c;
x->w=rands();
return x;
}
void init()
{
cnt=1; top=0;
null=&data[0];
null->sz=null->sum=0;
null->val=null->ls=null->rs=null->ss=-INF;
null->lzy1=0;
null->lzy2=-INF;
null->lft=null->rht=null;
}
//---------------------------------------------------------
void erase(Node *rt)
{
if(rt==null) return;
erase(rt->lft);
erase(rt->rht);
pool[++top]=rt;
}
int n,m;
char ord[20];
int a,b,c;
int main ()
{
init();
root=null;
n=fastget();
m=fastget();
for(int i=0;i<n;i++)
{
a=fastget();
root=merge(root,newnode(a));
}
while (m--)
{
scanf("%s",ord);
Node *p,*q,*r,*s;
if(ord[0]=='I')
{
a=fastget();
n=fastget();
root->split(a,p,q);
for(int i=0;i<n;i++)
{
b=fastget();
p=merge(p,newnode(b));
}
root=merge(p,q);
}else if(ord[0]=='D')
{
a=fastget();
b=fastget();
b=a+b-1;
root->split(a-1,p,q);
q->split(b-a+1,r,s);
erase(r);
root=merge(p,s);
}else if(ord[0]=='M' && ord[2]=='K')
{
a=fastget();
b=fastget();
c=fastget();
b=b+a-1;
root->split(a-1,p,q);
q->split(b-a+1,r,s);
r->same(c);
root=merge(p,merge(r,s));
}else if(ord[0]=='R')
{
a=fastget();
b=fastget();
b=b+a-1;
root->split(a-1,p,q);
q->split(b-a+1,r,s);
r->rev();
root=merge(p,merge(r,s));
}else if(ord[0]=='G')
{
a=fastget();
b=fastget();
b=a+b-1;
root->split(a-1,p,q);
q->split(b-a+1,r,s);
fastput(r->sum);
root=merge(p,merge(r,s));
}
else if(ord[0]=='M') fastput(root->ss);
}
return 0;
}
重量平衡樹&字尾平衡樹
BZOJ 3682: Phorni
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
template<class T>inline void read(T &res){
static char ch;T flag=1;
while((ch=getchar())<'0'||ch>'9')if(ch=='-')flag=-1;res=ch-48;
while((ch=getchar())>='0'&&ch<='9')res=(res<<1)+(res<<3)+ch-48;res*=flag;
}
#define N 500010
#define LL long long
int n,m,len,type,lastans,x,y;
int ch[N][2],rd[N],cl[N],cnt,root;
LL rk[N];
inline int randlmy(){
static int seed=173;
return seed=int(seed*48271LL%2147483647);
}
int cmp(int x,int y){
return cl[x]<cl[y]||(cl[x]==cl[y]&&rk[x-1]<rk[y-1]);
}
void rebuild(int &rt,LL l,LL r){
if(!rt)return;
rk[rt]=l+r;
LL mid=(l+r)>>1;
rebuild(ch[rt][0],l,mid);
rebuild(ch[rt][1],mid,r);
}
void rotate(int &p,int d,LL l,LL r){
int q=ch[p][d^1];
ch[p][d^1]=ch[q][d];
ch[q][d]=p;
p=q;
rebuild(p,l,r);
}
void insert(int &rt,LL l,LL r){
LL mid=(r+l)>>1;
if(!rt){rt=cnt;rk[rt]=l+r;return;}
if(cmp(cnt,rt)){insert(ch[rt][0],l,mid);if(rd[ch[rt][0]]>rd[rt])rotate(rt,1,l,r);}
else{insert(ch[rt][1],mid,r);if(rd[ch[rt][1]]>rd[rt])rotate(rt,0,l,r);}
}
void insert(int v){
cl[++cnt]=v;
rd[cnt]=randlmy()*randlmy();
insert(root,1,1LL<<61);
}
#define R(rt) rt<<1|1
#define L(rt) rt<<1
int minn[N<<2],p[N];
void build(int rt,int l,int r){
if(l==r)read(p[l]),minn[rt]=l;
else{
int mid=(l+r)>>1,lc=L(rt),rc=R(rt);
build(lc,l,mid);
build(rc,mid+1,r);
minn[rt]=rk[p[minn[lc]]]<=rk[p[minn[rc]]]?minn[lc]:minn[rc];
}
}
void updata(int rt,int l,int r,int id){
if(l==r)return;
int mid=(l+r)>>1,lc=L(rt),rc=R(rt);
if(id<=mid)updata(lc,l,mid,id);
else updata(rc,mid+1,r,id);
minn[rt]=rk[p[minn[lc]]]<=rk[p[minn[rc]]]?minn[lc]:minn[rc];
}
int query(int rt,int l,int r,int ql,int qr){
if(ql<=l&&r<=qr)return minn[rt];
int mid=(l+r)>>1,lc=L(rt),rc=R(rt);
if(qr<=mid)return query(lc,l,mid,ql,qr);
if(ql>mid)return query(rc,mid+1,r,ql,qr);
int vl=query(lc,l,mid,ql,qr),vr=query(rc,mid+1,r,ql,qr);
return rk[p[vl]]<=rk[p[vr]]?vl:vr;
}
char s[N],cmd[5];
int main(){
read(n),read(m),read(len),read(type);
scanf("%s",s);
for(register int i=1;i<=len;i++)
insert(s[len-i]-'a');
build(1,1,n);
while(m--){
scanf("%s",cmd);
if(!type)lastans=0;
if(cmd[0]=='I')
read(x),insert(x^lastans),++len;
else if(cmd[0]=='C')
read(x),read(p[x]),updata(1,1,n,x);
else
read(x),read(y),
printf("%d\n",lastans=query(1,1,n,x,y));
}
return 0;
}
可持久化Treap
POJ 3580 SuperMemo
#include<iostream>
#include<cstdio>
#include<cstring>
#include<ctime>
#include<cstdlib>
#include<algorithm>
using namespace std;
struct treap_node{
treap_node *left,*right;
int val,fix,size,wgt,minn,adel,rdel;
treap_node(int val): val(val) {left=right=NULL; fix=rand(); wgt=size=1; minn=val; rdel=adel=0; }
int lsize()
{
if (left)
return left->size;
else
return 0;
}
int rsize()
{
if (right)
return right->size;
else
return 0;
}
void updata()
{
minn=val;
if (left)
minn=min(minn,left->minn+left->adel);
if (right)
minn=min(minn,right->minn+right->adel);
}
void pushdown()
{
treap_node *temp;
if (adel)
{
minn+=adel;
val+=adel;
if (left)
left->adel+=adel;
if (right)
right->adel+=adel;
adel=0;
}
if (rdel%2)
{
if (left==NULL||right==NULL)
{
if (left==NULL)
{
left=right;
right=NULL;
}
else
{
right=left;
left=NULL;
}
}
else
{
temp=left;
left=right;
right=temp;
}
if (left)
left->rdel+=rdel;
if (right)
right->rdel+=rdel;
rdel=0;
}
updata();
}
void Maintain()
{
size=wgt;
size+=lsize()+rsize();
}
};
int n,m;
treap_node *root;
typedef pair<treap_node*,treap_node*> droot;
treap_node *merge(treap_node *a,treap_node *b)
{
if (!a) return b;
if (!b) return a;
a->pushdown(); b->pushdown();
a->updata(); b->updata();
if (a->fix<b->fix)
{
a->right=merge(a->right,b);
a->updata();
a->Maintain();
return a;
}
else
{
b->left=merge(a,b->left);
b->updata();
b->Maintain();
return b;
}
}
droot split(treap_node *a,int k)
{
if (!a) return droot(NULL,NULL);
droot y;
a->pushdown(); a->updata();
if (a->lsize()>=k)
{
y=split(a->left,k);
a->left=y.second;
a->updata();
a->Maintain();
y.second=a;
}
else
{
y=split(a->right,k-a->lsize()-1);
a->right=y.first;
a->updata();
a->Maintain();
y.first=a;
}
return y;
}
void insert(int k,int value)
{
treap_node *temp;
droot y=split(root,k);
temp=new treap_node(value);
root=merge(merge(y.first,temp),y.second);
}
void del(int k)
{
droot x,y;
x=split(root,k-1);
y=split(x.second,1);
root=merge(x.first,y.second);
}
int main()
{
char s[20];
droot ai,bi,ci;
treap_node *temp;
int i,x,y,a,L,t;
scanf("%d",&n);
for (i=1;i<=n;++i)
{
scanf("%d",&x);
insert(i,x);
}
scanf("%d",&m);
for (i=1;i<=m;++i)
{
scanf("%s",&s);
if (s[0]=='A')
{
scanf("%d%d%d",&x,&y,&a);
ai=split(root,x-1);
bi=split(ai.second,y-x+1);
bi.first->adel+=a;
ai.second=merge(bi.first,bi.second);
root=merge(ai.first,ai.second);
}
if (s[0]=='I')
{
scanf("%d%d",&x,&a);
insert(x,a);
}
if (s[0]=='D')
{
scanf("%d",&x);
del(x);
}
if (s[0]=='R')
{
if (s[3]=='E')
{
scanf("%d%d",&x,&y);
ai=split(root,x-1);
bi=split(ai.second,y-x+1);
bi.first->rdel++;
ai.second=merge(bi.first,bi.second);
root=merge(ai.first,ai.second);
}
if (s[3]=='O')
{
scanf("%d%d%d",&x,&y,&a);
L=y-x+1;
a=(a%L+L)%L;
ai=split(root,x-1);
bi=split(ai.second,L);
ci=split(bi.first,L-a);
bi.first=merge(ci.second,ci.first);
ai.second=merge(bi.first,bi.second);
root=merge(ai.first,ai.second);
}
}
if (s[0]=='M')
{
scanf("%d%d",&x,&y);
ai=split(root,x-1);
bi=split(ai.second,y-x+1);
t=bi.first->minn;
ai.second=merge(bi.first,bi.second);
root=merge(ai.first,ai.second);
printf("%d\n",t);
}
}
}
補一句,多年的超文字編輯器問題也解決了。。。。
TREAP最強,TREAP賽高!!
相關推薦
最強平衡樹——Treap[以我的最弱擊敗你的最強]
僕の最弱を以て,君の最強を打ち破る。!!——Treap 本人蒟蒻,在平衡樹坑中深陷數年。為了早日逃離此天坑,特作此文。 什麼是平衡樹?度娘傳送門 什麼是treap?ACdreamers%%% 注:本篇所有程式碼都在片尾!!(醒目) CMP 那麼瞭解了
【bzoj3224】普通平衡樹——treap
blog lib mes cas style tree upd treap ins 我的第一道treap題目,treap的模版題。 代碼是對著hzw的敲的,一邊敲一邊理解。。。 主要是熟悉一下treap的各種基本操作,詳細細節看代碼。 #include<cstdio
bzoj3224Tyvj 1728 普通平衡樹 treap
amp turn clas algo 。。 pac rip problem upd 3224: Tyvj 1728 普通平衡樹Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 17706 Solved: 7764[Submit
平衡樹Treap模板與原理
優化 排名 print 比較 pla ans for 後繼 每一個 這次我們來講一講Treap(splay以後再更) 平衡樹是一種排序二叉樹(或二叉搜索樹),所以排序二叉樹可以迅速地判斷兩個值的大小,當然操作肯定不止那麽多(不然我們還學什麽)。 而平衡樹在排序二叉樹的基礎上
luoguP3369[模板]普通平衡樹(Treap/SBT) 題解
names main getchar() clu 父親節 ble blank fine while 鏈接一下題目:luoguP3369[模板]普通平衡樹(Treap/SBT) #include<iostream> #include<cstdlib>
[洛谷P3369] 普通平衡樹 Treap & Splay
mes href using oid org 題目 scanf printf std 這個就是存一下板子...... 題目傳送門 Treap的實現應該是比較正經的。 插入刪除前驅後繼排名什麽的都是平衡樹的基本操作。 1 #include<cstdio>
7.Bzoj3224: Tyvj 1728 普通平衡樹(Treap)
Bzoj3224: Tyvj 1728 普通平衡樹(Treap) 終於自己敲出來了Treap。。。。。。拿來當板子還是挺好用的. 操作1,顯然根據二叉搜尋樹的性質直接建就好了. 操作2,如果有兩個兒子,則把這個點下旋下去,直到只有一個兒子或者沒有. 操作3,查詢比他小的數,記錄一個size,表示這個點有多少
【模板】平衡樹——Treap和Splay
二叉搜尋樹($BST$):一棵帶權二叉樹,滿足左子樹的權值均小於根節點的權值,右子樹的權值均大於根節點的權值。且左右子樹也分別是二叉搜尋樹。(如下) $BST$的作用:維護一個有序數列,支援插入$x$,刪除$x$,查詢排名為$x$的數,查詢$x$的排名,求$x$的前驅後繼等操作。 時間複雜度:$O(運
資料結構之平衡樹(Treap)
平衡樹是二叉搜尋樹和堆合併構成的新資料結構,所以它的名字取了Tree和Heap各一半,叫做Treap。 堆和樹的性質是衝突的,二叉搜尋樹滿足左子樹<根節點<右子樹,而堆是滿足根節點小於等於(或大於等於)左右兒子。因此在Treap的資料結構中,並不是
POJ 1442 平衡樹Treap新模板
題意:輸入m個數,詢問n個數,第一個數如果是3,就輸出在m的第三個數輸入完成後第1大的數,第二個就輸出第二大的數,但前提都是在輸入完U[i]個數後 思路:用平衡樹Treap進行插入和查詢第K大的數,模版題 #include <stdio.h> #include
BZOJ 1208 平衡樹Treap模版題
題意:不描述了 思路:我們只需要一個樹就可以,輸入一個數就存進去,當人和動物都大於0的時候,開始給人分配寵物,人的期望值b的排名k,找到k-1的數和k+1的數,比較哪個離b更近,人多還是動物動情況一樣不用分開討論,然後加起來取餘輸出,簡單題#include <std
洛谷P3369 普通平衡樹(Treap/Splay)
題目描述 您需要寫一種資料結構(可參考題目標題),來維護一些數,其中需要提供以下操作: 1. 插入x數 2. 刪除x數(若有多個相同的數,因只刪除一個) 3. 查詢x數的排名(若有多個相同的數,因輸出最小的排名) 4. 查詢排名為x的數 5.
【模板】普通平衡樹 Treap
題目描述 您需要寫一種資料結構(可參考題目標題),來維護一些數,其中需要提供以下操作: 1.插入x數 2.刪除x數(若有多個相同的數,因只刪除一個) 3.查詢x數的排名(排名定義為比當前數小的數的個數+1。若有多個相同的數,因輸出最小的排名) 4.查詢
重量平衡樹之Treap:以隨機優先級來維護堆結構,並滿足BST性質
神奇 upd 調整 cst clas 就是 int 元素 每一個 關於重量平衡樹的相關概念可以參考姊妹文章:重量平衡樹之替罪羊樹 Treap是依靠旋轉來維護平衡的重量平衡樹中最為好寫的一中,因為它的旋轉不是LL就是RR 對於每一個新的節點,它給這個節點分配了一個隨機數,用作
leetcode Minimum Depth of Binary Tree (平衡樹的最小深度)
leetcode 題目:https://leetcode.com/problems/minimum-depth-of-binary-tree/ Minimum Depth of Binary Tree ping 平衡樹的最小深度 解題思路: 1.遞迴求
史上最詳盡的平衡樹(splay)講解與模板
首先宣告:萬分感謝gty大哥的幫助!這年頭能找到簡單易懂的陣列版平衡樹模板只能靠學長了! 變數宣告:f[i]表示i的父結點,ch[i][0]表示i的左兒子,ch[i][1]表示i的右兒子,key[i]表示i的關鍵字(即結點i代表的那個數字),cnt[i]表示i結點的關鍵
2017-2018 ACM-ICPC Nordic Collegiate Programming Contest (NCPC 2017) 部分題/平衡樹/最小環/思路bfs
交題地址 難度按照順序遞增 J - Judging Moose 隊友敲的 #include <iostream> #include <cstdio> using namespace std; int main() {
我所見過的最簡短、最靈活的javascript日期轉字符串工具函數
var gets java cti return -m func date 靈活 我們知道javascript的Date對象並沒有提供日期格式化函數。將日期對象轉換成"2015-7-02 20:35:11"等這樣的格式又是項目中非經常常使用的需求。近期在我們項目中看到了
Behavior Tree 用 Lua 實現一個最簡行為樹
urn ret pri end put true for 行為樹 一個 1 local SELECTOR = 1 2 local SEQUENCE = 2 3 local CONDITION = 3 4 local ACTION = 4 5 6 loca
【BZOJ4519】[Cqoi2016]不同的最小割 最小割樹
main href family iostream 有趣的 rip tput ans val 【BZOJ4519】[Cqoi2016]不同的最小割 Description 學過圖論的同學都知道最小割的概念:對於一個圖,某個對圖中結點的劃分將圖中所有結點分成兩個部分,