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的树的左右节点编号。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#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\n", id+1); for(int i=0; i<=id; i++) printf("%d %d\n", ls[i], rs[i]); printf("%d\n", id); } return 0; }