您需要寫一種資料結構(可參考題目標題),來維護一些數,其中需要提供以下操作:
1. 插入x數
2. 刪除x數(若有多個相同的數,因只刪除乙個)
3. 查詢x數的排名(若有多個相同的數,因輸出最小的排名)
4. 查詢排名為x的數
5. 求x的前驅(前驅定義為小於x,且最大的數)
6. 求x的後繼(後繼定義為大於x,且最小的數)
第一行為n,表示操作的個數,下面n行每行有兩個數opt和x,opt表示操作的序號(1<=opt<=6)
對於操作3,4,5,6每行輸出乙個數,表示對應答案
10 1 106465
4 1
1 317721
1 460929
1 644985
1 84185
1 89851
6 81968
1 492737
5 493598
106465
84185
492737
1.n的資料範圍:n<=100000
2.每個數的資料範圍:[-1e7,1e7]
首先來說一下splay的基本操作:
void insert(int &k,int x,int lst)
t[k].size++;
if(t[k].v==x)t[k].w++;
else
if(t[k].v>x)insert(t[k].l,x,k);
else insert(t[k].r,x,k);
}
void del(int &k)
if(!(t[root].l&&t[root].r))
ans1=ans2=0
; get_pre(root,t[root].v);
get_pro(root,t[root].v);
splay(ans1,root);
splay(ans2,t[root].r);
int pos=t[t[root].r].l
; t[pos].l=t[pos].r=t[pos].size=t[pos].w=t[pos].v=t[pos].fa=0
; t[t[root].r].l=0
; update(t[root].r),update(root);
}
int get_x(int k,int x)
void get_pre(int k,int x)
void get_suf(int k,int x)
else get_suf(t[k].r,x);
}
說了這麼多大家可能覺得splay就相當於普通的二叉搜尋樹
但是splay有旋轉操作可以使樹變得平均
旋轉有兩種,單旋和雙旋:
單旋容易寫但是可以卡成每次o(n)
雙旋難寫但是可以使時間均攤到每次o(logn)
在這裡重點介紹雙旋
雙旋有三種情況
1.如果x的父節點是根,那麼直接旋上去
2.設x的父節點為y,y的父節點為z,y不為根節點,且x,y,z排列成一字形那麼我們先旋轉y到根節點,再旋轉x到根節點
3.設x的父節點為y,y的父節點為z,y不為根節點,且x,y,z排列成之字形那麼我們旋轉兩次x到根節點
證明複雜度
splay差不多就這些
上3224**
#include
#include
#include
#include
using
namespace
std;
int root,ans1,ans2,size;
struct splayt[200001];
inline
int in()
void update(int k)
void raxe(int x,int &k)
t[x].fa=z,t[y].fa=x,t[t[x].r].fa=y;
t[y].l=t[x].r,t[x].r=y;
update(y);update(x);
}void laxe(int x,int &k)
t[x].fa=z,t[y].fa=x,t[t[x].l].fa=y;
t[y].r=t[x].l,t[x].l=y;
update(y);update(x);
}void splay(int x,int &k)
if(t[t[x].fa].l==x)raxe(x,k);
else laxe(x,k);
}}void insert(int &k,int x,int lst)
t[k].size++;
if(t[k].v==x)t[k].w++;
else
if(t[k].v>x)insert(t[k].l,x,k);
else insert(t[k].r,x,k);
}void get_pre(int k,int x)
void get_pro(int k,int x)
else get_pro(t[k].r,x);
}int get(int k,int x)
void del(int &k)
if(!(t[root].l&&t[root].r))
ans1=ans2=0;
get_pre(root,t[root].v);
get_pro(root,t[root].v);
splay(ans1,root);
splay(ans2,t[root].r);
int pos=t[t[root].r].l;
t[pos].l=t[pos].r=t[pos].size=t[pos].w=t[pos].v=t[pos].fa=0;
t[t[root].r].l=0;
update(t[root].r),update(root);
}int get(int k,int x)
int main()
return
0;}
bzoj3224普通平衡樹
您需要寫一種資料結構 可參考題目標題 來維護一些數,其中需要提供以下操作 1.插入x數 2.刪除x數 若有多個相同的數,因只刪除乙個 3.查詢x數的排名 若有多個相同的數,因輸出最小的排名 4.查詢排名為x的數 5.求x的前驅 前驅定義為小於x,且最大的數 6.求x的後繼 後繼定義為大於x,且最小的...
BZOJ3224 普通平衡樹
題目傳送門 您需要寫一種資料結構 可參考題目標題 來維護一些數,其中需要提供以下操作 1.插入x數 2.刪除x數 若有多個相同的數,因只刪除乙個 3.查詢x數的排名 若有多個相同的數,因輸出最小的排名 4.查詢排名為x的數 5.求x的前驅 前驅定義為小於x,且最大的數 6.求x的後繼 後繼定義為大於...
BZOJ3224 普通平衡樹
您需要寫一種資料結構 可參考題目標題 來維護一些數,其中需要提供以下操作 1.插入x數 2.刪除x數 若有多個相同的數,因只刪除乙個 3.查詢x數的排名 若有多個相同的數,因輸出最小的排名 4.查詢排名為x的數 5.求x的前驅 前驅定義為小於x,且最大的數 6.求x的後繼 後繼定義為大於x,且最小的...