傳送門
 
文章目錄
 
題意:
 
給你n,dn,dn,d,讓你構造有nnn個點的二叉樹,他們每個節點深度和為ddd。
 n,d≤3000n,d\le 3000n,d≤3000.
 
思路:
 
先考慮不能構造出來的情況,設sumsumsum為最小的深度和,那么sum>dsum>dsum>d或n?(n?1)2<d\frac{n*(n-1)}{2}<d2n?(n?1)?<d的時候無解。
 考慮構造的深度最小的情況,我們讓每個點iii的父親等于?i2?\left \lfloor \frac{i}{2} \right \rfloor?2i??即可,這樣深度最小,我們先讓d=d?sumd=d-sumd=d?sum。記最長鏈的最下端的編號為ppp,那么當我們depth[p]?depth[i]+1<ddepth[p]-depth[i]+1<ddepth[p]?depth[i]+1<d的時候,我們直接讓iii跑到ppp的下面,讓后將ppp更新為iii就好了。如果depth[p]?depth[i]+1>=ddepth[p]-depth[i]+1>=ddepth[p]?depth[i]+1>=d,那么說明如果跳到這個點深度就多了,那么我們就向上找ppp的父親,每跳一次,就讓d??d--d??,直到ddd為000,將iii放到跳到的點的下面就好了。
 
#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<map>
#include<cmath>
#include<cctype>
#include<vector>
#include<set>
#include<queue>
#include<algorithm>
#include<sstream>
#include<ctime>
#include<cstdlib>
#define X first
#define Y second
#define L (u<<1)
#define R (u<<1|1)
#define pb push_back
#define mk make_pair
#define Mid (tr[u].l+tr[u].r>>1)
#define Len(u) (tr[u].r-tr[u].l+1)
#define random(a,b) ((a)+rand()%((b)-(a)+1))
#define db puts("---")
using namespace std
;
typedef long long LL
;
typedef unsigned long long ULL
;
typedef pair
<int,int> PII
;const int N
=1000010,mod
=1e9+7,INF
=0x3f3f3f3f;
const double eps
=1e-6;int n
,d
;
int depth
[N
],fa
[N
];int main()
{
int _
; scanf("%d",&_
);while(_
--){scanf("%d%d",&n
,&d
);int sum
=0; depth
[0]=-1; int root
=1;for(int i
=1;i
<=n
;i
++) {if((i
&(i
-1))==0) root
=i
;depth
[i
]=depth
[i
/2]+1,fa
[i
]=i
/2,sum
+=depth
[i
];}if(sum
>d
||d
>n
*(n
-1)/2) { puts("NO"); continue; }d
-=sum
;if(!d
){puts("YES");for(int i
=2;i
<=n
;i
++) printf("%d ",fa
[i
]);puts("");continue;}for(int i
=n
;i
>=1;i
--){if((i
&(i
-1))==0) continue;int cnt
=depth
[root
]-depth
[i
]+1;if(cnt
<d
){d
-=cnt
;depth
[i
]=depth
[root
]+1;fa
[i
]=root
;root
=i
;}else {d
=cnt
-d
;while(d
&&root
!=1) root
=fa
[root
],d
--;fa
[i
]=root
; depth
[i
]=depth
[root
]+1;puts("YES");for(int i
=2;i
<=n
;i
++) printf("%d ",fa
[i
]);puts("");break;}} }return 0;
}
                            總結
                            
                                以上是生活随笔為你收集整理的Codeforces Round #624 (Div. 3)  E. Construct the Binary Tree  思维 + 构造的全部內容,希望文章能夠幫你解決所遇到的問題。
                            
                            
                                如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。