二逼平衡樹 樹套樹(線段樹套Splay平衡樹)

2022-05-07 08:24:08 字數 2927 閱讀 6208

題面

bzoj3196

解析線段樹和splay兩棵樹套在一起,常數直逼inf,但最終僥倖過了

思路還是比較簡單, 在原陣列維護乙個下標線段樹,再在每乙個線段樹節點,維護乙個對應區間的權值splay。簡單說一下操作:

0.提取區間

1.查詢區間內k的排名

提取區間,找到區間內所有的splay, 分別比k小的數的個數,相加後加一即可

2.查詢區間第k大

提取區間,找到區間內所有的splay,因為有多棵splay,這個操作顯然不能像一般的splay一樣查詢,只能二分答案,轉化為操作一,再check排名就行

3.單點修改

4.求前驅

同樣找到區間內的所有splay,分別進入找前驅,輸出最大的前驅即可。但k可能不在splay中,於是我們先要找到大於等於k的權值最小的節點,將它旋轉到根,再找前驅,但由於可能沒有前驅,就在每棵splay插入-inf, 查詢排名時記得減去即可

5.求後繼

操作與前驅類似,找到小於等於k的權值最大的節點,旋轉到根,找後繼,記得每棵splay插入inf就行

大部分操作都是自己yy的,可能不是很優秀,但我這個又臭又長的**並沒有除錯多久,也是不容易啊。

**(340行):

#includeusing

namespace

std;

const

int maxn = 100005, inf = 2147483647

;template

void read(t &re)

int n, m, root[maxn<<1

], rt, a[maxn];

int tot, cnt, lson[maxn<<1], rson[maxn<<1

], stak[maxn], top, s[maxn], snum;

struct

splay_treetr[maxn * 20

];void update(int

x)void rotate(int

x)void splay(int x, int to, int

id)

if(!to)

root[id] =x;

}void insert(int x, int

v)

if(now)

tr[now].num ++;

else

splay(now,

0, x);

}void build(int &x, int l, int

r)void extract(int x, int l, int r, int l, int

r)

int mid = (l + r)>>1

;

if(l <=mid)

extract(lson[x], l, r, l, mid);

if(mid

extract(rson[x], l, r, mid + 1

, r);

}int queryrk(int id, int

x)

else

if(x ==tr[now].val)

else

}tr[

0].s[1] =root[id];

splay(now,

0, id);

return

ret;

}int work1(int

x)

return ret + 1;}

int check(int

x)int work2(int

x) top = 0

;

return

ret;

}int find(int now, intx)}

int querypre(int

now)

int querynxt(int

now)

void modify(int x, int pos, int l, int r, int

v)

else

update(nxt);update(pre);

insert(x, v);

if(l ==r)

int mid = (l + r)>>1

;

if(pos <=mid)

modify(lson[x], pos, l, mid, v);

else

modify(rson[x], pos, mid + 1

, r, v);

}int findmx(int now, int

x)

else

now =rs;

}return

ret;

}int findmn(int now, int

x)

else

now =ls;

}return

ret;

}int work3(int

x)

return

ret;

}int work4(int

x)

return

ret;

}int

main()

else

if(opt == 2

)

else

if(opt == 3

)

else

if(opt == 4

)

else

}return0;

}

view code

BZOJ3196 二逼平衡樹 線段樹套Splay

您需要寫一種資料結構 可參考題目標題 來維護乙個有序數列,其中需要提供以下操作 1.查詢k在區間內的排名 2.查詢區間內排名為k的值 3.修改某一位值上的數值 4.查詢k在區間內的前驅 前驅定義為小於x,且最大的數 5.查詢k在區間內的後繼 後繼定義為大於x,且最小的數 第一行兩個數 n,m 表示長...

bzoj3196 二逼平衡樹 線段樹套平衡樹

題目描述 寫一種資料結構,來維護乙個有序數列,其中需要提供以下操作 1.查詢k在區間內的排名 2.查詢區間內排名為k的值 3.修改某一位值上的數值 4.查詢k在區間內的前驅 前驅定義為小於x,且最大的數 5.查詢k在區間內的後繼 後繼定義為大於x,且最小的數 輸入格式 第一行兩個數n,m n,m 5...

樹套樹 線段樹套set

請你寫出一種資料結構,來維護乙個長度為 n 的序列,其中需要提供以下操作 1 pos x,將 pos 位置的數修改為 x。2 l r x,查詢整數 x 在區間 l,r 內的前驅 前驅定義為小於 x,且最大的數 數列中的位置從左到右依次標號為 1 n。區間 l,r 表示從位置 l 到位置 r 之間 包...