题目链接:https://www.luogu.org/problem/CF1214E
题意:你需要构造出一个节点数为 2n 的一棵树. 给出 n 个范围在 [1,n] 的正整数 di . 你构造出来的树需要满足: 第 2i−1 个点与第 2i 个点在树上的距离恰为di.
这里定义两个点 u , v 之间的距离为 u 到 v 路径上的边数.
如果有多种方案, 输出任意一种即可.
分析:先将2,4,6...2n按照d的大小从大到小排序形成一条主链,之后奇数点都在这条主链上添加(题目已说过d<=n)
对于主链上的第i个点,然后我们枚举i,然后对于每个i∈[1,n] 只需要执行下面两步就完了:
- 设链上的第i个点是 ai, 那么令 x=ai+di−1 ,将 2i−1 与 x 连一条边.
- 如果 x 是目前链上的最后一个点, 那么把 ai−1 放在链尾, 链长度 +1 .
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn=1e5+7; const int N=1e3+7; const int inf=0x3f3f3f3f; struct node{ int d,pos; bool operator < (const node &a){ return d>a.d; } }a[maxn]; vector<int> v; int main(){ int n;scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d",&a[i].d); a[i].pos=i<<1; } sort(a+1,a+1+n); for(int i=1;i<n;i++) { printf("%d %d ",a[i].pos,a[i+1].pos); v.push_back(a[i].pos); } v.push_back(a[n].pos); for(int i=1;i<=n;i++){ int d=a[i].d+i-2;//a[i].d+i是指的本身对应的那个点所处的位置,-1就是与它相连的主链上的点,这里又减了一次1是因为vector下标从0开始的 printf("%d %d ",v[d],a[i].pos-1); if(d==v.size()-1) v.push_back(a[i].pos-1);//如果要与之相连的点已经在最后面了,需要再加一点 } return 0; }