题意:
给定一个二叉树和节点值,修改一个节点的费用为1,求最小修改成二叉搜索树的费用。
思路:
本题应该考虑二叉搜索树的性质,一棵二叉搜索树的中序遍历是一个严格上升的子序列,那么这道题就转换成求一个求这个树中序遍历后的最长上升子序列了,但是出于一些数据,这道题这样求只能拿部分分,而正解是先中序遍历,然后每个节点在线性数组中就有了一个位置,那么这个节点的值还要减去在自己在数组中的位置,那么这是为什么。设原数为a[i],中序遍历位置为i,那么就是a[i]-i=t,那么这个t表示的就是这个值离自己中序遍历的位置的距离.
求LIS时要用 nlog(n) 的算法
代码:
program pro;
type
tre=record
lc,rc:longint;
end;
var
f,g:array[0..201000] of longint;
a,b:array[0..201000] of longint;
tot,n:longint;
tree:array[0..201000] of tre;
procedure openf;
begin
assign(input,'bst.in'); reset(input);
assign(output,'bst.out'); rewrite(output);
end;
procedure closef;
begin
close(input);
close(output);
end;
procedure dfs(t:longint);
begin
if t=0 then exit;
dfs(tree[t].lc);
inc(b[0]);
b[b[0]]:=a[t];
dfs(tree[t].rc);
end;
procedure init;
var
i,fa,t:longint;
begin
readln(n);
for i:=1 to n do read(a[i]);
for i:=2 to n do
begin
readln(fa,t);
if t=0 then tree[fa].lc:=i;
if t=1 then tree[fa].rc:=i;
end;
dfs(1);
end;
procedure main;
var
i,l,r,mid:longint;
begin
for i:=1 to n do b[i]:=b[i]-i;
tot:=0;
g[0]:=-maxlongint;
for i:=1 to n do
begin
if b[i]>=g[tot] then
begin
inc(tot);
g[tot]:=b[i];
continue;
end;
l:=1; r:=tot;
while l<r do
begin
mid:=(l+r) shr 1;
if b[i]>=g[mid] then l:=mid+1
else r:=mid;
end;
g[l]:=b[i];
end;
writeln(n-tot);
end;
begin
openf;
init;
main;
closef;
end.
转自:
Eme-sina博客