题意:
给你
n
,
d
n,d
n,d,让你构造有
n
n
n个点的二叉树,他们每个节点深度和为
d
d
d。
n
,
d
≤
3000
n,d\le 3000
n,d≤3000.
思路:
先考虑不能构造出来的情况,设
s
u
m
sum
sum为最小的深度和,那么
s
u
m
>
d
sum>d
sum>d或
n
∗
(
n
−
1
)
2
<
d
\frac{n*(n-1)}{2}<d
2n∗(n−1)<d的时候无解。
考虑构造的深度最小的情况,我们让每个点
i
i
i的父亲等于
⌊
i
2
⌋
\left \lfloor \frac{i}{2} \right \rfloor
⌊2i⌋即可,这样深度最小,我们先让
d
=
d
−
s
u
m
d=d-sum
d=d−sum。记最长链的最下端的编号为
p
p
p,那么当我们
d
e
p
t
h
[
p
]
−
d
e
p
t
h
[
i
]
+
1
<
d
depth[p]-depth[i]+1<d
depth[p]−depth[i]+1<d的时候,我们直接让
i
i
i跑到
p
p
p的下面,让后将
p
p
p更新为
i
i
i就好了。如果
d
e
p
t
h
[
p
]
−
d
e
p
t
h
[
i
]
+
1
>
=
d
depth[p]-depth[i]+1>=d
depth[p]−depth[i]+1>=d,那么说明如果跳到这个点深度就多了,那么我们就向上找
p
p
p的父亲,每跳一次,就让
d
−
−
d--
d−−,直到
d
d
d为
0
0
0,将
i
i
i放到跳到的点的下面就好了。
// Problem: E. Construct the Binary Tree
// Contest: Codeforces - Codeforces Round #624 (Div. 3)
// URL: https://codeforces.com/contest/1311/problem/E
// Memory Limit: 256 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)
//#pragma GCC optimize("Ofast,no-stack-protector,unroll-loops,fast-math")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4.1,sse4.2,avx,avx2,popcnt,tune=native")
//#pragma GCC optimize(2)
#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;
//void rd_cre() { freopen("d://dp//data.txt","w",stdout); srand(time(NULL)); }
//void rd_ac() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//AC.txt","w",stdout); }
//void rd_wa() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//WA.txt","w",stdout); }
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()
{
// ios::sync_with_stdio(false);
// cin.tie(0);
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;
}
/*
*/