樹套樹學習筆記

2021-08-30 15:10:03 字數 2949 閱讀 8775

題目:傳送門

這是第一類入門級的樹套樹,線段樹/樹狀陣列套平衡樹。用線段樹或樹狀陣列維護區間,再用平衡樹維護對區間中的動態修改。相對於普通的直白操作會好一些,但會帶好幾個log

有人可能會疑惑為什麼為每個區間開一棵平衡樹不會mle呢?我們以線段樹為例,每一層的線段樹的節點數都為n,至多有logn層。為每乙個區間開一棵和區間大小相同的平衡樹,總的平衡樹大小只會在nlogn左右。

關於五個操作

其實關鍵就是一句話紮實的**實現能力是複雜演算法的基礎

1、查詢k在[l,r]的排名;對treap原來的求排名函式稍作修改為求比k小的數的個數。這樣線段樹分段查詢再合併加1,就是k在l-r的排名。

時間複雜度:(log2n)[線段樹,平衡樹]

2、查詢在[l,r]的區間中排名為k的元素。這個操作真沒有什麼高深的做法,二分值大小吧,再用操作一暴力。聽說隔壁「線段樹/樹狀陣列套主席樹」可以只帶兩個log,平衡樹表示無奈。

時間複雜度:(log3n)[二分,線段樹,平衡樹]

3、將位置為pos的元素值修改為k。這個也很簡單(暴力),線段樹列舉pos所在的log個區間,每次從平衡樹中刪去原值,插入新值。

4、查詢k在[l,r]中的前驅(要求嚴格小於)。線段樹劃分區間,再用平衡樹暴力求各區間的前驅,最後合併前驅。

5、查詢k在[l,r]中的後繼(要求嚴格大於)。對操作四依葫蘆畫瓢。

【code】

這裡將treap封裝成了結構體,方便線段樹的呼叫。

#include

#include

#include

#include

#define ls t[x].ch[0]

#define rs t[x].ch[1]

using

namespace std;

const

int inf=

2147483647

;const

int maxn=

5e4+

1000

;int n,m;

int p[maxn]

;struct node

;node t[maxn*40]

;int tot;

struct treap

void

rotate

(int

&x,int d)

void

insert

(int

&x,int val)

t[x]

.size++;if

(t[x]

.val==val)

int d=val>t[x]

.val;

insert

(t[x]

.ch[d]

,val);if

(t[x]

.key>t[t[x]

.ch[d]

].key)

rotate

(x,d);}

void

delet

(int

&x,int val)

bool d=t[ls]

.key>t[rs]

.key;

if(ls==

0||rs==

0) x=ls+rs;

else

rotate

(x,d)

,delet

(x,val);}

else t[x]

.size--

,delet

(t[x]

.ch[t[x]

.val,val);}

intrank

(int x,

int val)

intkth

(int x,

int k)

}int

pre(

int x,

int val)

intnxt

(int x,

int val)

}a[maxn<<2]

;inline

void

read

(int

&x)inline

void

read

(int

&x,int

&y)inline

void

read

(int

&x,int

&y,int

&z)void

build

(int x,

int l,

int r)

intqueryrank

(int x,

int l,

int r,

int ql,

int qr,

int num)

intqueryval

(int ql,

int qr,

int k)

return ans;

}void

modify

(int x,

int l,

int r,

int pos,

int k)

intquerypre

(int x,

int l,

int r,

int ql,

int qr,

int k)

intquerynxt

(int x,

int l,

int r,

int ql,

int qr,

int k)

intmain()

else

if(op==2)

else

if(op==3)

else

if(op==4)

else

}return0;

}

樹套樹 學習筆記

樹套樹像他的名字一樣,就是一棵樹套另一棵樹。用一棵外層樹來維護一些區間之類的東西。然後外層樹的每個節點都是一棵內層樹。就這樣 bzoj3196 這是一道線段樹套平衡樹的模板題。外層用一棵線段樹來維護區間操作。然後線段樹的每個節點都是一棵平衡樹 操作1 查詢從l到r中比k小的數的個數,然後 1輸出即可...

模板 樹套樹

xsy2685 lg3380 bzoj3196 tyvj1730 二逼平衡樹 1.查詢k在區間內的排名 乙個數的排名是小於這個數的個數 1 2.查詢區間內排名為 k 的值 3.修改某一位值上的數值 4.查詢 k 在區間內的前驅 前驅定義為小於 x 且最大的數 5.查詢 k 在區間內的後繼 後繼定義為...

樹套樹專題

對資料結構的不熟練 題目鏈結 嘗試一下樹狀陣列套主席樹的寫法。小細節沒有重視 為了方便起見,一般我們寫getrank x 求的都是 1 include2 const int maxn 50035 3 const int maxnode 5000035 4 const int inf 21474836...