Codeforces Round #386 (Div. 2) 746G(树的构造)

大体题意

一棵树有n个结点,告诉你每层深度上有a[i]个结点,以及有多少叶子结点

让你生成这棵树

题解:考虑一颗树,如果满足每层深度上有a[i]结点,最多能有多少叶子结点

   那么答案很简单,就是对(a[i]-1)求和再加1(每一层的结点都集中在上一层的一个结点上)

     同理,我们考虑最少能有多少叶子结点,就是把上一个的答案再减去min(a[i]-1, a[i-1]-1)的求和,就是每一层的结点都尽可能的分散在上一层的结点上

   根据这个,那么如果要求有k个叶子节点,k在最大值与最小值之间,就可以生成出这棵树了

   生成的方法,和构造起来差不多,就是先求出最大值与k的差T,然后每一层处理时,如果T>0,就使这一层尽可能的分散在上一层结点上,然后T减少一点

   直到T为0,之后的层都直接集中在上一层的一个结点即可

#include <iostream>
#include <cstdio>
using namespace std;
const int maxn = 2*111111;
int n, t, k;
int a[maxn];
int main()
{
    cin>>n>>t>>k;
    for(int i = 1; i <= t; i++) cin>>a[i];
    int ans = 0;
    for(int i = 1; i < t; i++) ans += (a[i]-1); ans += a[t];
    int ans2 = ans;
    for(int i = 2; i <= t; i++) ans2 -= min(a[i-1]-1, a[i]-1);
    if(k <= ans && k >= ans2)
    {
        int T = ans - k;
        cout<<n<<endl;
        for(int i = 2; i <= 1+a[1]; i++)
            cout<<"1 "<<i<<endl;
        int tot = 2+a[1];
        for(int i = 2; i <= t; i++)
        {
            int tt = min(a[i-1]-1, a[i]-1), ttt = 0;
            while(T > 0 && tt > 0)
            {
                if(ttt > 0) { T--; tt--; }
                cout<<tot-a[i-1]+ttt<<" "<<tot+ttt<<endl;
                ttt++;
            }
            if(T == 0 || tt == 0)
            {
                while(ttt < a[i])
                {
                    cout<<tot-a[i-1]<<" "<<tot+ttt<<endl;
                    ttt++;
                }
            }
            tot += a[i];
        }
    } else
    {
        cout<<"-1"<<endl;
    }
}
原文地址:https://www.cnblogs.com/Saurus/p/6197311.html