改造二叉樹

2022-03-25 22:20:40 字數 2063 閱讀 1289

【題目描述】

小y在學樹論時看到了有關二叉樹的介紹:在電腦科學中,二叉樹是每個結點最多有兩個子結點的有序樹。通常子結點被稱作「左孩子」和「右孩子」。二叉樹被用作二叉搜尋樹和二叉堆。隨後他又和他人討論起了二叉搜尋樹。

什麼是二叉搜尋樹呢?二叉搜尋樹首先是一棵二叉樹。設key[p]表示結點p上的數值。對於其中的每個結點p,若其存在左孩子lch,則key[p]>key[lch];若其存在右孩子rch,則key[p]小y與他人討論的內容則是,現在給定一棵二叉樹,可以任意修改結點的數值。修改乙個結點的數值算作一次修改,且這個結點不能再被修改。若要將其變成一棵二叉搜尋樹,且任意時刻結點的數值必須是整數(可以是負整數或0),所要的最少修改次數。相信這一定難不倒你!請幫助小y解決這個問題吧。

【輸入格式】

第一行乙個正整數n表示二叉樹結點數。結點從1~n進行編號。

第二行n個正整數用空格分隔開,第i個數ai表示結點i的原始數值。

此後n - 1行每行兩個非負整數fa, ch,第i + 2行描述結點i + 1的父親編號fa,以及父子關係ch,(ch = 0 表示i + 1為左兒子,ch = 1表示i + 1為右兒子)。

結點1一定是二叉樹的根。

【輸出格式】

僅一行包含乙個整數,表示最少的修改次數。

【樣例輸入】

3

2 2 2

1 0

1 1

【樣例輸出】

2

【資料範圍】

20 % :n <= 10 , ai <= 100.

40 % :n <= 100 , ai <= 200

60 % :n <= 2000 .

100 % :n <= 10 ^ 5 ,  ai < 2 ^ 31.

題解:

①將二叉搜尋樹轉換為中序遍歷序列

②嘗試通過改變元素使得原序列變成嚴格單增的序列

③美妙處理:用原序列第i個數減去i形成新序列,然後進行不嚴格單增最長子序列dp

④上述做法原理:防止兩個數之間會有很多數從而不滿足單增,因此先使每個元素大小向前靠一位

⑤最後答案就是用nlogndp中的最優值d減n:ans=n-d

#include#define go(i,a,b) for(int i=a;i<=b;i++)

const int n=100003;

int n,ch[n][2],u,_,t,d,l,r,m,val[n],a[n],d[n],j;

void dfs(int u)

int main()

{ scanf("%d",&n);

go(i,1,n)scanf("%d",val+i);

go(i,2,n)scanf("%d%d",&u,&_),ch[u][_]=i;dfs(1);

go(i,1,n)a[i]-=i;d[d=1]=a[1];

go(i,2,n)if(a[i]>=d[d])d[++d]=a[i];

else

{ j=l=0,r=d;

while(l<=r)m=l+r>>1,d[m]<=a[i]?j=l=m+1:r=m-1;

if(a[i]某天夜半忽然醒來,像被命運叫醒了,它說你不能就這樣過完一生。————《你曾是少年》

改造二叉樹

description 小y在學樹論時看到了有關二叉樹的介紹 在電腦科學中,二叉樹是每個結點最多有兩個子結點的有序樹。通常子結點被稱作 左孩子 和 右孩子 二叉樹被用作二叉搜尋樹和二叉堆。隨後他又和他人討論起了二叉搜尋樹。什麼是二叉搜尋樹呢?二叉搜尋樹首先是一棵二叉樹。設key p 表示結點p上的數...

改造二叉樹(bst)

題目大意 給你一棵二叉樹,讓你改變最少的結點上的數值,使這棵二叉樹變成bst,求這個需要改變的最少的結點數。演算法 二分 dp 一開始就沒理解題目問的真正內涵,想了半天的樹型dp,結果肯定是果斷不對,看了題解才知道bst就是二叉樹中序遍歷之後保持有序,進一步得知其實就是要我們求lis。將這棵二叉樹中...

改造二叉樹 Tree LTS

noip2014模擬10.26 改造二叉樹 standard io time limits 1000 ms memory limits 262144 kb description 小y在學樹論時看到了有關二叉樹的介紹 在電腦科學中,二叉樹是每個結點最多有兩個子結點的有序樹。通常子結點被稱作 左孩子 ...