改造二叉树

题目

小Y在学树论时看到了有关二叉树的介绍:在计算机科学中,二叉树是每个结点最多有两个子结点的有序树。通常子结点被称作“左孩子”和“右孩子”。二叉树被用作二叉搜索树和二叉堆。随后他又和他人讨论起了二叉搜索树。
什么是二叉搜索树呢?二叉搜索树首先是一棵二叉树。设key[p]表示结点p上的数值。对于其中的每个结点p,若其存在左孩子lch,则key[p]>key[lch];若其存在右孩子rch,则key[p]

题意

给你一棵普通的二叉树,让你变成一棵二叉排序树(搜索树)需要至少改变多少次。

分析

我们可以先画个图,我们会发现一个重要的事:
若一棵二叉树按中序遍历排序时一个最长不上升的序列,那么这是一棵二叉搜索树
那么我们会想到去用原先的二叉树去排中序遍历后去做最长不下降子序列,然后用总节点个数-最长不下降个数便为答案了。
但是这是不够的,题目的限制是整数
那么2,3,1,4这个序列的答案便是1,但实际是2
我们要继续寻找解决的方法,刚刚的问题是两数之间没有整数,那么:
a,b,a+1,那么很明显b是不合法的,那么我们如何限制它呢?
我们可以把它们减去它们的下标(即A1-1,A2-2,A3-3….An-n)
为什么这样是可以的呢?
因为:
若有两个数ai,aj,(分别为b,b+n)且这两个数是在最长不下降子序列中的
那么b,b+n之间有j-i-1个整数,但是实际只能插上n-1个数。
所以就是这样

var
    fa,a,f,b,d:array[0..100000] of longint;
    son:array[0..100000,1..2] of longint;
    i,n,m,x,y,l,r,mid,en,st:longint;
function min(l,r:longint):longint;
begin
    if l>r then exit(r) else exit(l);
end;
procedure dfs(k:longint);
begin
    if k=0 then exit;
    dfs(son[k,1]);
    inc(st);b[st]:=a[k];
    dfs(son[k,2]);
end;
begin
     readln(n);
     for i:=1 to n do read(a[i]);
     for i:=2 to n do begin
         read(x,y);
         if y=1 then son[x,2]:=i else son[x,1]:=i;
         fa[i]:=x;
     end;
     dfs(1);
     for i:=1 to st do b[i]:=b[i]-i;
     en:=1;d[1]:=b[1];
     for i:=2 to st do begin
         if b[i]>=d[en] then begin inc(en);d[en]:=b[i];end
         else begin
             l:=1;r:=en;
             while l<>r do begin
                mid:=(l+r)shr 1;
                if d[mid]<=b[i] then l:=mid+1 else r:=mid;
             end;
             d[l]:=min(d[l],b[i]);
         end;
     end;
     writeln(n-en);
end.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值