眾所周知,二叉查詢樹的形態和鍵值的插入順序密切相關。準確的講:1、空樹中加入乙個鍵值k,則變為只有乙個結點的二叉查詢樹,此結點的鍵值即為k;2、在非空樹中插入乙個鍵值k,若k小於其根的鍵值,則在其左子樹中插入k,否則在其右子樹中插入k。
我們將一棵二叉查詢樹的鍵值插入序列稱為樹的生成序列,現給出乙個生成序列,求與其生成同樣二叉查詢樹的所有生成序列中字典序最小的那個,其中,字典序關係是指對兩個長度同為n的生成序列,先比較第乙個插入鍵值,再比較第二個,依此類推。
輸入格式:
第一行,乙個整數,n,表示二叉查詢樹的結點個數。第二行,有n個正整數,k1到kn,表示生成序列,簡單起見,k1~kn為乙個1到n的排列。
輸出格式:
一行,n個正整數,為能夠生成同樣二叉查詢數的所有生成序列中最小的。
輸入樣例#1:複製
41 3 4 2
輸出樣例#1:複製
1 3 2 4
對於20%的資料,n ≤ 10。
對於50%的資料,n ≤ 100。
對於100%的資料,n ≤ 100,000。
先看出題目是直接建樹然後貪心輸出中序遍歷。
然後交上去。發現如果樹是鏈的話就被卡成\(o(n^2)\)。
怎麼辦呢?點開題解
發現題解多是笛卡爾樹。
笛卡爾樹是什麼鬼東西(蒟蒻表示不會啊)
那就去學(抄題解)吧。
笛卡爾樹類似於\(treap\)。
維護兩個值,乙個為\(key\)值即點權值,另乙個在本題維護為\(id\),即出現順序。
笛卡爾樹是利用單調棧的特性建樹的。
按樣例的\(key\)值從小到大排序後。
\(id\)值為\(1,4,2,3.\)
我們先把\(1\)放進樹。
然後讓\(1\)點連右兒子\(key\)值為\(2\),\(id\)為\(4\)的點。
然後\(key\)值為\(3\)時,前面的\(2\)的\(id\)比3的\(id\)大。
即按中序遍歷,\(3\)的左兒子是\(2\)。
於是就斷開\(1\)連向\(2\)的邊,然後連向\(3\),並讓\(3\)向\(2\)連一條邊作為左兒子。
建樹的性質就是這樣的。
\(o(n)\)建樹。
先上\(o(n^2)\)寫法
#include#include#include#include#includeusing namespace std;
const int n=1000001;
struct nodet[n<<1];
int ch[n],n,cnt=1,ans[n],tot;
int read()
while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
return x*w;
}void build(int x)ch[n],t[n];
int n,tot,line[n];
int read()
while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
return x*w;
}bool cmp(node a,node b)
dfs(t[0].ch[1]);
return 0;
}
SGU155 笛卡爾樹的構造
分類 資料結構 2013 09 07 20 12 300人閱讀收藏 舉報題目 題意 給出每個點的兩個值key和fix,且所有的key值和fix值都是不相同的,要求構造出笛卡爾樹。輸入每個點的兩個權 值,輸出笛卡爾樹每個結點 按照輸入的順序編號 的父親結點和兩個兒子的編號。分析 首先,笛卡爾樹對於ke...
笛卡爾樹 中序遍歷判斷是否為二叉搜尋樹
笛卡爾樹是一種特殊的二叉樹,其結點包含兩個關鍵字k1和k2。首先笛卡爾樹是關於k1的二叉搜尋樹,即結點左子樹的所有k1值都比該結點的k1值小,右子樹的所有k1值都比該結點的k1值大。其次所有結點的k2值滿足優先佇列 不妨設為最小堆 的順序要求,即該結點的k2值比其子樹中的所有k2值小。給定一棵二叉樹...
單調棧的應用 笛卡爾樹與虛樹
何為笛卡爾樹?對於一組關係 fa,ls,rs 滿足 pri fa geqslant max pri ls pri rs 以及 val rs geqslant val fa geqslant val ls 如何構建笛卡爾樹?按照 val 順序順序插入 n 個點 那麼,新插入的點一定會插入到最右邊 最大...