TJOI2011 樹的序(貪心,笛卡爾樹)

2022-04-29 21:57:18 字數 1702 閱讀 4101

眾所周知,二叉查詢樹的形態和鍵值的插入順序密切相關。準確的講: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 個點 那麼,新插入的點一定會插入到最右邊 最大...