CodeForces 1214E Petya and Construction Set 构造

http://codeforces.com/problemset/problem/1214/E
题目大意:你需要构造出一个节点数为 2 n 2n 2n的一棵树. 给出 n n n个范围在 [ 1 , n ] [1,n] [1,n]的正整数 d i d_{i} di。你构造出来的树需要满足:第 2 i − 1 2i−1 2i1个点与第 2 i 2i 2i 个点在树上的距离恰为 d i d_{i} di。这里定义两个点 u u u , v v v 之间的距离为 u u u v v v路径上的边数.如果有多种方案,输出任意一种即可。

思路:因为给定的距离只关系到 2 i 2i 2i 2 i − 1 2i-1 2i1,因此考虑先把偶数点(或奇数点)全部拿出来构成一条链,再决定剩余点怎么加。当然这条链不是随便构成的,应该按照 d d d从大到小排序,这样我们一定可以构造出满足题意的树。严格的证明我是不会,但是可以大概解释一下。我们从 d i < = n d_{i}<=n di<=n这个性质入手,因为我们先处理的是 d i d_{i} di比较大的点,此时如果距离 < n <n <n,那么一定可以在该链的某个点上加一个分叉点来实现,如果距离等于 n n n,那么一定可以把这个点加到当前链的末尾,递推下去不难发现是一定有解的。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#define pr pair<int,int>
using namespace std;

const int maxn=1e5+5;

struct node
{
    int id,v;
    bool operator <(const node &a)const
    {
        return v>a.v;
    }
}a[maxn<<1];
vector<pr> vec;
int n;

int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i].v),a[i].id=2*i;
    sort(a+1,a+1+n);
    for(int i=1;i<n;i++)
        vec.push_back(pr(a[i].id,a[i+1].id));
    int len=n,tmp;
    for(int i=1;i<=n;i++)
    {
        tmp=a[i+a[i].v-1].id;
        if(tmp==a[len].id)//加到链尾上
            a[++len].id=a[i].id-1;
        vec.push_back(pr(a[i].id-1,tmp));
    }
    len=vec.size();
    for(int i=0;i<len;i++)
        printf("%d %d\n",vec[i].first,vec[i].second);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值