CF Gym 102059F Fake Plastic Trees

链接:https://codeforces.com/gym/102059/problem/F

题意:构造一棵有n(n<1e18)个叶子节点的二叉树,左子树的大小等于右子树或者比右子树大一,构造的树可以多次使用。

   输出树的个数(最多125棵树),后面每行输出树的左子树的编号,和右子树的编号,最后输出根节点的编号,(从0开始)。

题解:递归构造二叉树,相同的大小的树不用重复构造,用map<long long, int>做一个查询, ls[ ], rs[ ]分别记录编号为id的树的左右节点编号。

#include <bits/stdc++.h>
using namespace std;

const int maxn=2e5+5;
int id, ls[maxn], rs[maxn];
map<long long, int> mp;

void init()
{
    mp.clear(); id=-1;
}

void build(long long n)
{
    if(mp.find(n)!=mp.end()) return ; //该大小的树已经构造过
    if(n==1){
        mp[n]=++id; ls[id]=-1; rs[id]=-1;
        return ;
    }
    build(n-n/2); build(n/2);
    mp[n]=++id; ls[id]=mp[n-n/2]; rs[id]=mp[n/2];
}

int main()
{
    //freopen("in.txt", "r", stdin);
    int T;
    for(cin>>T; T--; )
    {
        init();
        long long n;
        cin>>n;
        build(n);
        printf("%d
", id+1);
        for(int i=0; i<=id; i++)
            printf("%d %d
", ls[i], rs[i]);
        printf("%d
", id);
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/Yokel062/p/11661108.html