1773【RMQ&LCA】Cartesian Tree(笛卡尔树)

2019-03-15 13:02

【RMQ&LCA】Cartesian Tree(笛卡尔树)

Time Limit:1000MS Memory Limit:65536K

Total Submit:6 Accepted:6

Description

笛卡尔树(tree.pas/c/cpp)

【问题描述】

让我们考虑一种特殊的二叉查找树,叫做笛卡尔树。回想一下,二叉查找树是有根有序的二叉树,这样,对于它的每一个节点x满足以下条件:在它的左子树的每个节点的数值小于x的数值,它的右子树的每个节点的数值大于x的数值。也就是说,如果我们用L(x)表示结点x的左子树,用R(x)表示结点x右子树,用kx表示该结点x的数值,那么对每个结点x我们有 如果y ∈ L(x),那么ky < kx 如果z ∈ R(x),那么kz > kx

若一棵二叉查找树被称为笛卡尔树,那么它的每一个结点x除了主要数值kx外还有一个附加数值ax,且这个数值符合堆的条件,即 如果y是x的父亲,那么ay < ax

因此,一棵笛卡尔树是一棵有根有序的二叉树,这样,它的每个节点拥有两个数值(k , a)和满足上述的三个条件。

给出一系列点,构建出它们的笛卡尔树,或检测构建出它们的笛卡尔树是不可能的。

Input

第一行包括一个整数N(1 <= N <= 50 000),表示你要构建的笛卡尔树的点的对数。

接下来N行包括两个数字,k,a,|k|, |a| <= 30 000,保证每行的k和a是不同的。

Output

如果能构建出笛卡尔树则在第一行输出YES否则输出NO。

如果是YES,则在接下来N行输出这棵树。第i+1行输出第i个结点的父亲,左儿子,右儿子。如果这个结点无父亲或者儿子,则用0代替。 输入保证能构建出笛卡尔树的只有一种情况。

Sample Input

7 5 4 2 2 3 9 0 5 1 3 6 6 4 11

Sample Output

YES 2 3 6 0 5 1 1 0 7 5 0 0 2 4 0 1 0 0 3 0 0

Hint

本题数据不完整,请在本系统测试通过后到http://poj.org/problem?id=2201 提交完整测试!

Source

Northeastern Europe 2002, Northern Subregion

一开始看错题目,以为输入的第二个数字为K,纠结了很久也没有构造出一棵笛卡尔树。

先把数据按k从小到大排序,所得为树的中序遍历。

找出这棵树中a值最小的为该树的根,在排序中 根左面a值最小的为该树的左子树,在排序中 根右面a值最小的为该树的右子树。找最小值时,要用ST算法。 原作者:

var n:longint;

a:array[0..50000+1,1..3]of longint; f:array[0..16]of longint;

mi:array[0..50000+1,0..16,1..2]of longint; o:array[0..50000+1,1..3]of longint;

procedure init; var i:longint; begin f[0]:=1;

for i:=1 to 16 do f[i]:=f[i-1]*2; read(n);

for i:=1 to n do begin read(a[i,1],a[i,2]); a[i,3]:=i; end; end;

procedure qsort(l,r:longint); var i,j,k:longint; begin

if l>=r then exit;

i:=l; j:=r; k:=a[(l+r) div 2,1]; while i

while a[i,1]k do dec(j); if i<=j then begin

a[0]:=a[i]; a[i]:=a[j]; a[j]:=a[0]; inc(i); dec(j); end; end;

qsort(l,j); qsort(i,r); end;

procedure dfs(l,r:longint); var i,t,ft,lt,rt,x:longint; begin

if r<=l then exit;

t:=trunc(ln(r-l+1)/ln(2));

if mi[l,t,1]

if l<>x then begin

t:=trunc(ln(x-l)/ln(2));

if mi[l,t,1]

if r<>x then begin

t:=trunc(ln(r-x)/ln(2));

if mi[x+1,t,1]

o[ft,2]:=lt; o[ft,3]:=rt; o[lt,1]:=ft; o[rt,1]:=ft;

dfs(l,x-1); dfs(x+1,r); end;

procedure main; var i,b,t:longint; begin

for i:=1 to n do mi[i,0,1]:=a[i,2]; for i:=1 to n do mi[i,0,2]:=i; for t:=1 to trunc(ln(n)/ln(2)) do for b:=1 to n-f[t]+1 do

if mi[b,t-1,1]>mi[b+f[t-1],t-1,1] then mi[b,t]:=mi[b+f[t-1],t-1] else mi[b,t]:=mi[b,t-1]; dfs(1,n); end;

procedure print; var i:longint; begin

writeln('YES'); for i:=1 to n do

writeln(o[i,1],' ',o[i,2],' ',o[i,3]); end;

begin init;

qsort(1,n); main; print; end.

程序1:(我一直用integer,搞得Running ERROR n次) var i,j,n:longint;

k,a,b:array[0..50001] of longint; mn:array[0..50001,0..16] of longint; d:array[0..50001,1..3] of longint;

procedure kp(l,r:longint); var x,y,z:longint; begin

i:=l; j:=r; x:=k[i]; y:=a[i]; z:=b[i]; repeat

while (ix) do dec(j); if i

k[i]:=k[j]; a[i]:=a[j]; b[i]:=b[j]; inc(i); end;

while (i

k[j]:=k[i]; a[j]:=a[i]; b[j]:=b[i]; dec(j); end; until i>=j;

k[i]:=x; a[i]:=y; b[i]:=z; if l

procedure rmq1(n:longint); begin

for i:=1 to n do mn[i,0]:=i; for i:=1 to trunc(ln(n)/ln(2)) do for j:=1 to n do begin mn[j,i]:=mn[j,i-1]; if j+(1<<(i-1))<=n then

if a[mn[j,i]]>a[mn[j+(1<<(i-1)),i-1]] then mn[j,i]:=mn[j+(1<<(i-1)),i-1]; end; end;

function rmq(l,r:longint):longint; var x:longint; begin

x:=trunc(ln(r-l+1)/ln(2));

if a[mn[l,x]]

else exit(mn[r-(1<

end;

procedure dfs(l,r:longint); var x,y,z:longint; begin

if l=r then exit; x:=rmq(l,r); y:=0; z:=0;

if x<>l then begin y:=rmq(l,x-1);

if (k[y]a[x]) then begin d[b[x],2]:=b[y]; d[b[y],1]:=b[x]; dfs(l,x-1); end; end;

if x<>r then begin z:=rmq(x+1,r);

if (k[z]>k[x]) and (a[z]>a[x]) then begin d[b[x],3]:=b[z]; d[b[z],1]:=b[x]; dfs(x+1,r); end; end; end;

begin

readln(n);

for i:=1 to n do begin

readln(k[i],a[i]); b[i]:=i; end; kp(1,n); rmq1(n); dfs(1,n);

writeln('YES');

for i:=1 to n do writeln(d[i,1],' ',d[i,2],' ',d[i,3]); end.


1773【RMQ&LCA】Cartesian Tree(笛卡尔树).doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: