Misha walked through the snowy forest and he was so fascinated by the trees to decide to draw his own tree!

Misha would like to construct a rooted tree with n

vertices, indexed from 1 to 1

.

Below there is a tree with 6

vertices. The subtree of vertex 4

.

CodeForces - 1098.DIV1.C: Construct a tree(贪心,构造)

The branching coefficient of the tree is defined as the maximum number of children in any vertex. For example, for the tree above the branching coefficient equals 2

. Your task is to construct a tree with s

, and the branching coefficient is minimum possible.

Input

The only input line contains two integers n

and 10

).

Output

If the required tree does not exist, output «No». Otherwise output «Yes» on the first line, and in the next one output integers 2

, i

.

Examples
Input
3 5
Output
Yes
1 1 
Input
4 42
Output
No
Input
6 15
Output
Yes
1 2 3 1 5 
Note

Below one can find one of the possible solutions for the first sample case. The sum of subtree sizes equals 5

, and the branching coefficient equals 2

.

CodeForces - 1098.DIV1.C: Construct a tree(贪心,构造)

Below one can find one of the possible solutions for the third sample case. The sum of subtree sizes equals 15

, and the branching coefficient equals 2

.

CodeForces - 1098.DIV1.C: Construct a tree(贪心,构造)

 

 

题意:给定N,S,让你构造一个大小为N的数,使得每个节点子树大小之和为S,如果存在,请构造一个树,使得儿子最多的点的儿子数量(P)最少。

思路:我们发现对于大小一定的树,越瘦长K越大(一条链,最大为N*(N+1)/2),越矮胖越小(菊花树,最小为N+N-1),那么如果K不在这个范围我们输出-1;如果在,我们一定看i有构造一个满足题意的树。 我们可以二分得到P。然后来构造。 我的构造方式是先构造一条链,此时的sum=N*(N+1)/2;如果sum>S,我们就把最下面的点移到上面的某个位置,知道sum=S。

#include<bits/stdc++.h>
#define ll long long
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=1000010;ll N,S;
ll fa[maxn],q[maxn],d[maxn],head,tail,sz[maxn],son[maxn];
bool check(ll Mid)
{
    ll tN=N,now=1,p=1,res=0;
    while(tN){
        res+=min(p,tN)*now;
        if(res>S) return false;
        tN-=min(p,tN);
        p*=Mid; now++;
    } return true;
}
int main()
{
    cin>>N>>S;
    ll Mn=N+N-1; ll Mx=N*(N+1)/2;
    if(S<Mn||S>Mx) return puts("NO"),0;
    ll L=1,R=N-1,Mid,res;
    while(L<=R){
        Mid=(L+R)/2;
        if(check(Mid)) res=Mid,R=Mid-1;
        else L=Mid+1;
    }
    puts("YES");
    rep(i,1,N) sz[i]=1; ll Now=Mx,D=2;
    for(int i=N;;i--){
        if(Now==S) break;
        if(sz[D]==sz[D-1]*res) D++;
        if(Now-S>=i-D){
            sz[D]++; sz[i]--;
            Now-=(i-D);
        }
        else {
            sz[i]--; sz[i-(Now-S)]++;
            Now=S;
        }
    }
    head=tail=1; q[head]=1; d[1]=1;
    ll p=1;
    rep(i,2,N) {
        if(sz[i]==0) break;
        L=p+1; R=p+sz[i];
        rep(j,L,R){
            while(d[q[head]]!=i-1||son[q[head]]==res){
                head++;
            }
            fa[j]=q[head]; son[q[head]]++;
            q[++tail]=j; d[j]=i;
        }
        p=R;
    }
    rep(i,2,N) printf("%lld ",fa[i]);
    return 0;
}

 

相关文章: