https://codeforc.es/contest/1214/problem/E
题目大意:
给你di,要求你构造一棵树满足点i*2与i*2-1距离为di。
胡乱写了一通,过了,但不知道是不是正解。
以di和其对应的点编号为一组,以di从小到大排序。
建立足够长的链
先将第一对点插入。
之后的点对,先将一个点插入最左边的点的左边
然后看另一个点能否插入,如果能插入,就插入链中
如果不能,就与前一个点相连
注意有些细节,比如什么时候该存图之类的
#include <iostream> #include <stdio.h> #include <stdlib.h> #include <algorithm> #include <vector> #define MAXN 1000010 using namespace std; int n; struct Pair{ int d,id,l,r; }p[MAXN]; vector<int> fl[MAXN*4]; vector<int> li[MAXN*2]; bool p_cmp1(Pair a,Pair b) { return a.d<b.d; } void Connect(int u,int v) { li[u].push_back(v); li[v].push_back(u); } int main() { scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&p[i].d); p[i].id=i; p[i].l=i*2-1,p[i].r=i*2; } for(int i=0;i<=n*4;i++) fl[i].push_back(0); sort(p+1,p+n+1,p_cmp1); int l=2*n+1; for(int i=1;i<=n;i++) { l--; int u=p[i].l,v=p[i].r,d=p[i].d; fl[l][0]=u; Connect(u,fl[l+1][0]); if(fl[l+d][0]==0) { fl[l+d][0]=v; for(int j=1;j<fl[l+d].size();j++) Connect(fl[l+d][j],v); if(fl[l+d+1][0]) Connect(fl[l+d+1][0],v); if(fl[l+d-1][0]) Connect(fl[l+d-1][0],v); } else { fl[l+d-1].push_back(v); if(fl[l+d-1][0]) Connect(fl[l+d-1][0],v); } } for(int i=1;i<=2*n;i++) { for(int j=0;j<li[i].size();j++) if(i<li[i][j]) printf("%d %d ",i,li[i][j]); } return 0; }