洛谷[USACO22JAN] Tests for Haybales G
你要选定一个数 k k k并构造一个数组 x i x_i xi,满足 x 1 ≤ x 2 ≤ ⋯ ≤ x n x_1\leq x_2\leq \cdots\leq x_n x1≤x2≤⋯≤xn,且对于每一个 i i i,都满足 j i j_i ji为使得 x j i ≤ x i + k x_{j_i}\leq x_i+k xji≤xi+k的最大的位置。给出 j i j_i ji,并满足 i ≤ j i i\leq j_i i≤ji以及 j 1 ≤ j 2 ≤ ⋯ ≤ j n ≤ n j_1\leq j_2\leq \cdots\leq j_n\leq n j1≤j2≤⋯≤jn≤n。
输出 k k k和数组 x i x_i xi,需满足 1 ≤ k ≤ 1 0 18 1\leq k\leq 10^{18} 1≤k≤1018, 0 ≤ x i ≤ 1 0 18 0\leq x_i\leq 10^{18} 0≤xi≤1018
1 ≤ n ≤ 1 0 5 1\leq n\leq 10^5 1≤n≤105
首先,我们可以将 j i j_i ji都加上 1 1 1,那其意义就变为了第一个大于 x i + k x_i+k xi+k的位置。
建一棵 n + 1 n+1 n+1个节点的数,对于每个节点 i i i,以 j i + 1 j_i+1 ji+1作为父亲并连一条边,那么根节点就为 n + 1 n+1 n+1。
对于每一层,我们需要这一层的节点比它的每一个儿子的值大 k k k以上。那么,我们可以将深度为 d e p dep dep的点的 x x x值定为 ( n + 1 − d e p ) × k + t ( 0 ≤ t < k ) (n+1-dep)\times k+t(0\leq t
t t t需要满足:
我们发现, d f s dfs dfs序与这个条件正好相反。那么,我们令 t = k − d f n i t=k-dfn_i t=k−dfni。因为连边时是从小到大,所以遍历时是从大到小,编号越大, d f n i dfn_i dfni就越小, k − d f n i k-dfn_i k−dfni就越大。
需要满足 k > n k>n k>n,还要注意 x i x_i xi的范围。
时间复杂度为 O ( n ) O(n) O(n)。
#include
using namespace std;
int n,x,tot=0,dfn=0,d[200005],l[200005],r[200005];
long long k=1e6,v[200005],ans[200005];
void add(int xx,int yy){
l[++tot]=r[xx];d[tot]=yy;r[xx]=tot;
}
void dfs(int u){
ans[u]=v[u]*k-(++dfn);
for(int i=r[u];i;i=l[i]){
v[d[i]]=v[u]-1;
dfs(d[i]);
}
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&x);
add(x+1,i);
}
v[n+1]=n+1;dfs(n+1);
printf("%lld\n",k);
for(int i=1;i<=n;i++){
printf("%lld\n",ans[i]);
}
return 0;
}