題目大意:
給定乙個數列,定義兩種操作:
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...