ZOJ 2112 線段樹套平衡樹

2021-08-18 18:15:38 字數 1704 閱讀 7013

題目大意:

給定乙個數列,定義兩種操作:

1、修改第n個數的值

2、求[l,r]區間內第k大的值。

方法:線段樹維護區間,treap樹維護第k大(splay當然也可以)

樹套樹第一題。。沒想到真的是每個線段樹上的節點建一棵平衡樹。。。。。

然後修改值就是在所有相關區間內的平衡樹里,erase乙個值再insert乙個值。。。。簡直恐怖

查詢就是二分答案,因為每個區間都有一棵樹,所以可以很快就可以在o(lgn)裡算出這個區間內比查詢數大的數字有多少個,滿足區間加法,最後判斷 比判斷的這個數大的數是否 <= k,然後可以保證最後乙個匹配邊界值一定是數列裡存在的數。

真是不自己調過一遍的程式沒法徹底理解!!!

二分判斷是否第k大和求第k大還是有細微差別的。

二分判斷要考慮 key[x] == val 的情況 , 而求第k大只需要判斷是否找的下去就行

#include #define lson(x) (x<<1)

#define rson(x) (x<<1|1)

#define clr(arr) memset(arr,0,sizeof(arr))

using namespace std;

int n = 0 , m = 0;

const int maxn = 1020000;

int tmp = 0;

int root[maxn],treapcnt,key[maxn],priority[maxn], //root陣列儲存每個區間的根節點所對應的平衡數節點的的編號

childs[maxn][2],cnt[maxn],size[maxn];

inline void update(int x)

inline void rotate(int& x, int t)

void _insert(int& x, int k)

} else

update(x); }

void _erase(int& x, int k)

int t = priority[ childs[x][0] ] > priority[ childs[x][1] ];

rotate(x,t);

_erase(x,k);

} } else

update(x);}

void build(int k , int l , int r , int x , int num)

void change(int k, int l , int r ,int x ,int num,int y)

void finds(int k, int num)

else

finds( childs[k][0], num);

}void query(int k , int l , int r , int x ,int y, int num)

int mid = (l + r) >> 1;

if(mid >= y)

query(lson(k),l,mid,x,y,num);

else if (mid < x)

query(rson(k),mid+1,r,x,y,num);

else }

int a[maxn];

int main()

else

printf("%d\n",l);

} }

} return 0;

Zoj 2112 線段樹套Treap

樹套樹入門題 樹套樹空間複雜度分析 維護乙個長度為n的序列,線段樹的結點數一般為4n,而treap則是對於每乙個元素 包括重複出現的 都需要乙個空間,那麼第1層的所需要的空間為 1 n 第二層為 2 n 2 所以其實為o h n.那麼所需的空間為o nlog n 但在實際運用中,所形成的線段樹往往不...

zoj 2112 主席樹套樹狀陣列

現在把主席樹的原理給弄清楚了,從i 1開始,每次新插入乙個數,就為他建一棵線段樹 當然第一次i 0的時候是建一棵空樹 線段樹裡面儲存的是1 i的樹的位置情況 簡單來說,如果有m個樹,則每棵線段樹都是範圍為1 m的,至於1 i沒有m個那就先讓它空著不管,我只負責1 i裡面的數的位置情況插入到線段樹裡面...

zoj 2112 主席樹套樹狀陣列 優化

題解思路 如果直接對原來的陣列建立主席樹套樹狀陣列的空間複雜度是 n m log n m log n m 這樣明顯 那麼我們可以對原來的數組建主席樹模型,空間複雜度就是n logn,對m裡面的修改建主席樹套樹狀陣列空間複雜度是m logm logm明顯小了很多。include define lson...