CF1214E Petya and Construction Set(树上构造)

/*
 *author: zlc
 *zucc_acm_lab
 *just do it
 */
/*
 *cf1214e
 *题意:
 *给你2n个点,输入n个数,第i个数di表示i*2和i*2-1之间的距离为di
 *请你构造这棵树并输出
 *构造树的一般方法是先造一条长链,然后在链上加分支
 *先对长度数组从大到小排序
 *构造出一条长度为n的链
 *链的第i个位置放di所连的一个点
 *如果i+di-1等于当前链的长度,就让链长度加1,把另一个点接上
 *如果不是,就把另一点当成分支接在i+di-1个点后面
 */
#include<bits/stdc++.h> 
using namespace std;
typedef long long ll;
const double pi=acos(-1.0);
const double eps=1e-6;
const int mod=1e9+7;
const int inf=1e9;
const int maxn=2e5+100;
inline int read () {int x=0,f=1;char ch=getchar();while (ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=getchar();}while (ch>='0'&&ch<='9') {x=x*10+ch-'0';ch=getchar();}return x*f;}
ll qpow (ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
int n;
int a[maxn];
vector<int> g[maxn];
struct qnode {
    int w,id;
    bool operator < (const qnode &r) const {
        return w>r.w;
    }
}d[maxn];
int main () {
    n=read();
    for (int i=1;i<=n;i++) {
        d[i].w=read();
        d[i].id=i;
    }
    sort(d+1,d+n+1);
    int tot=n;
    for (int i=1;i<=n;i++) {
        a[i]=d[i].id*2-1;
        if (i+d[i].w-1>=tot) 
            a[++tot]=d[i].id*2;
        else
            g[i+d[i].w-1].push_back(d[i].id*2);
    }
    for (int i=1;i<tot;i++) {
        printf("%d %d
",a[i],a[i+1]);
        for (auto v:g[i]) 
            printf("%d %d
",a[i],v);
    }
} 
原文地址:https://www.cnblogs.com/zhanglichen/p/13657479.html