1. 程式人生 > >[COGS 2421] [HZOI 2016] 簡單的Treap 笛卡爾樹

[COGS 2421] [HZOI 2016] 簡單的Treap 笛卡爾樹

printf 搜索樹 images for bsp lin 維護 區間 stdout

笛卡爾樹就是你給兩維限制,一維堆R,一維二叉搜索樹K,平地拔起一棵Treap,最廣範的應用:用LCA求區間最值,建Treap,還有個什麽範圍top k我表示並不會查都查不到。它最妙最高的地方在於用棧來建樹:我們可以先排序K然後一個個插入,那麽我們都是最右端,橫容易被卡,那麽我們不從上到下,我們從下到上,用棧維護,那就把時間復雜度從O(n^2)降到O(n),具體過程見下圖從圖一到圖二就是這麽一個過程,我們在把K為13的點插入時要找到一個合適的位置,上比他大,下比他小(假設大根堆)

技術分享技術分享

下面見代碼

#include<cstdio>
#include<algorithm>
#define
MAXN 500010 using namespace std; inline int read() { int sum=0; char ch=getchar(); while(ch<0||ch>9)ch=getchar(); while(ch>=0&&ch<=9) { sum=(sum<<1)+(sum<<3)+ch-0; ch=getchar(); } return sum; } struct Treap { int key,r; Treap *ch[2]; }*stack[MAXN],node[MAXN],*root;
int top; int n; int comp(const Treap a,const Treap b) { return a.key<b.key; } inline void Init() { n=read(); for(int i=1;i<=n;i++)node[i].key=read(); for(int i=1;i<=n;i++)node[i].r=read(); sort(node+1,node+n+1,comp); } inline void Build() { stack[++top]=node+1; for(int i=2;i<=n;i++) { Treap
*last=NULL; while(top&&stack[top]->r>node[i].r) last=stack[top--]; if(top)stack[top]->ch[1]=node+i; node[i].ch[0]=last; stack[++top]=node+i; } root=stack[1]; } void dfs(Treap *p) { if(!p)return; printf("%d ",p->key); dfs(p->ch[0]); dfs(p->ch[1]); } int main() { int __size__=128<<20; char *__p__=(char*)malloc(__size__)+__size__; __asm__("movl %0, %%esp\n"::"r"(__p__)); freopen("treap.in","r",stdin); freopen("treap.out","w",stdout); Init(); Build(); dfs(root); return 0; }

[COGS 2421] [HZOI 2016] 簡單的Treap 笛卡爾樹