[atARC103F]Distance Sums

给定$n$个数$d_{i}$,构造一棵$n$个点的树使得$\forall 1\le i\le n,\sum_{j=1}^{n}dist(i,j)=d_{i}$

其中$dist(i,j)$表示$i$到$j$的路径上所经过的边数,若无解输出-1

$2\le n\le 10^{5}$,$1\le d_{i}\le 10^{12}$,保证$d_{i}$各不相同

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define N 100005
 4 #define pli pair<long long,int>
 5 #define fi first
 6 #define se second
 7 vector<pli>e;
 8 int n,sz[N];
 9 pli d[N];
10 int main(){
11     scanf("%d",&n);
12     for(int i=1;i<=n;i++){
13         scanf("%lld",&d[i].fi);
14         d[i].se=i;
15     }
16     sort(d+1,d+n+1);
17     for(int i=1;i<=n;i++)sz[i]=1;
18     for(int i=n;i>1;i--){
19         int fa=lower_bound(d+1,d+i+1,make_pair(d[i].fi+(2*sz[i]-n),0))-d;
20         if (d[fa].fi!=d[i].fi+(2*sz[i]-n)){
21             printf("-1");
22             return 0;
23         }
24         sz[fa]+=sz[i];
25         e.push_back(make_pair(d[fa].se,d[i].se));
26     }
27     for(int i=2;i<=n;i++)d[1].fi-=sz[i];
28     if (d[1].fi)printf("-1");
29     else
30         for(int i=0;i<n-1;i++)printf("%d %d\n",e[i].fi,e[i].se);
31 }
View Code

 

posted @ 2020-11-10 16:09  PYWBKTDA  阅读(106)  评论(0编辑  收藏  举报