E. Construct the Binary Tree。。。

Posted lijiahui-123

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了E. Construct the Binary Tree。。。相关的知识,希望对你有一定的参考价值。

You are given two integers nn and dd . You need to construct a rooted binary tree consisting of nn vertices with a root at the vertex 11 and the sum of depths of all vertices equals to dd .

A tree is a connected graph without cycles. A rooted tree has a special vertex called the root. A parent of a vertex vv is the last different from vv vertex on the path from the root to the vertex vv . The depth of the vertex vv is the length of the path from the root to the vertex vv . Children of vertex vv are all vertices for which vv is the parent. The binary tree is such a tree that no vertex has more than 22 children.

You have to answer tt independent test cases.

Input

The first line of the input contains one integer tt (1t10001≤t≤1000 ) — the number of test cases.

The only line of each test case contains two integers nn and dd (2n,d50002≤n,d≤5000 ) — the number of vertices in the tree and the required sum of depths of all vertices.

It is guaranteed that the sum of nn and the sum of dd both does not exceed 50005000 (n5000,d5000∑n≤5000,∑d≤5000 ).

Output

For each test case, print the answer.

If it is impossible to construct such a tree, print "NO" (without quotes) in the first line. Otherwise, print "{YES}" in the first line. Then print n1n−1 integers p2,p3,,pnp2,p3,…,pn in the second line, where pipi is the parent of the vertex ii . Note that the sequence of parents you print should describe some binary tree.

Example
Input
Copy
3
5 7
10 19
10 18
Output
Copy
YES
1 2 1 3 
YES
1 2 3 3 9 9 2 1 6 
NO
Note

Pictures corresponding to the first and the second test cases of the example:

技术图片技术图片

 

题解:

Tutorial

1311E - Construct the Binary Tree

This problem has an easy constructive solution. We can find lower and upper bounds on the value of dd for the given nn. If the given dd does not belong to this segment, then the answer is "NO". Otherwise, the answer is "YES" for any dd in this segment.

How to construct it? Let‘s start from the chain. The answer for the chain is the upper bound of dd and it is n(n1)2n(n−1)2. Then let‘s try to decrease the answer by 11 in one move. Let‘s take some leaf vv (the vertex without children) with the smallest depth that is not bad and try to move it up. The definition of badness will be below. To do this, let‘s find such vertex pp that its depth is less than the depth of vv by 22 and it has less than 22 children. If we found such vertex pp then let‘s make vv the child of pp and decrease the answer by one.

If we didn‘t find such vertex pp, I claim that the vertex vv has the minimum possible depth it can have and we should not consider it in the future. Let‘s mark this vertex as bad and continue our algorithm.

If at some moment we cannot find any not bad leaf vv, then the answer is "NO". Otherwise, the answer is "YES".

Time complexity: O(nd)O(nd).

 

Solution

#include <bits/stdc++.h>

using namespace std;

int main() {
#ifdef _DEBUG
	freopen("input.txt", "r", stdin);
//	freopen("output.txt", "w", stdout);
#endif
	
	int t;
	cin >> t;
	while (t--) {
		int n, d;
		cin >> n >> d;
		int ld = 0, rd = n * (n - 1) / 2;
		for (int i = 1, cd = 0; i <= n; ++i) {
			if (!(i & (i - 1))) ++cd;
			ld += cd - 1;
		}
		if (!(ld <= d && d <= rd)) {
			cout << "NO" << endl;
			continue;
		}
	
		vector<int> par(n);
		iota(par.begin(), par.end(), -1);
		
		vector<int> cnt(n, 1);
		cnt[n - 1] = 0;
		
		vector<int> bad(n);
		
		vector<int> dep(n);
		iota(dep.begin(), dep.end(), 0);
		
		int cur = n * (n - 1) / 2;
		while (cur > d) {
			int v = -1;
			for (int i = 0; i < n; ++i) {
				if (!bad[i] && cnt[i] == 0 && (v == -1 || dep[v] > dep[i])) {
					v = i;
				}
			}
			assert(v != -1);
			int p = -1;
			for (int i = 0; i < n; ++i) {
				if (cnt[i] < 2 && dep[i] < dep[v] - 1 && (p == -1 || dep[p] < dep[i])) {
					p = i;
				}
			}
			if (p == -1) {
				bad[v] = 1;
				continue;
			}
			assert(dep[v] - dep[p] == 2);
			--cnt[par[v]];
			--dep[v];
			++cnt[p];
			par[v] = p;
			--cur;
		}
	
		cout << "YES" << endl;
		for (int i = 1; i < n; ++i) cout << par[i] + 1 << " ";
		cout << endl;
	}
		
	return 0;
}

//转载于http://codeforces.com/blog/entry/74224

以上是关于E. Construct the Binary Tree。。。的主要内容,如果未能解决你的问题,请参考以下文章

Codeforces Round #250 (Div. 1)E. The Child and Binary Tree

CF1311E Construct the Binary Tree

Codeforces1107 E. Vasya and Binary String(区间dp)

E. William The Oblivious(线段树)

E. William The Oblivious(线段树)

105. Construct Binary Tree from Preorder and Inorder Traversal