题目
题意:已知一个长度为
n
(
1
<
=
n
<
=
1
0
5
)
n(1<=n<=10^5)
n(1<=n<=105)的未知的非递减数组
a
i
a_i
ai。已知,对于数组中每个元素
a
i
a_i
ai,不小于
a
i
+
k
a_i+k
ai+k的最大下标为
x
i
x_i
xi,即
a
x
i
<
=
a
i
+
k
<
a
x
i
+
1
a_{x_i}<=a_i+k<a_{x_i+1}
axi<=ai+k<axi+1。根据这一条条件,有
x
1
<
=
x
2
<
=
.
.
.
<
=
x
n
x_1<=x_2<=...<=x_n
x1<=x2<=...<=xn。
现给定
x
1
,
x
2
,
.
.
.
,
x
n
x_1,x_2,...,x_n
x1,x2,...,xn,构造
k
k
k和对应的
a
a
a数组
参考
思路:对于位置
i
i
i上的数,我们给它构造父节点
x
i
+
1
x_i+1
xi+1,表示位置
x
i
+
1
x_i+1
xi+1是第一个大于
a
x
i
+
k
a_{x_i}+k
axi+k的位置。根据
x
i
x_i
xi的定义,我们可以构造得到一棵树,根节点为
n
+
1
n+1
n+1。
如样例2 2 4 5 6 6,对应的树为
我们令
k
=
n
+
1
k=n+1
k=n+1
对于不同高度的元素,乘上对应深度的k,保证,高度大的元素,大于次高的元素+k。
对于相同高度的元素,为保证
a
a
a数组的非递减,要保证下标大的元素,更大。因此,我们给它们一个偏移值,下标大的元素,大于下标小的元素。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 100010;
vector<int> ve[maxn];
int val[maxn], deep[maxn];
int n, x, value, k;
ll a[maxn];
void dfs(int u, int d) {
deep[u] = d;
val[u] = value--;// value为全局偏移值
int sz = ve[u].size();
// 倒序遍历,保证同层的情况下,遍历下标大的元素,
// 使val[pos1] < val[pos2], pos1<pos2 && deep[pos1]==deep[pos2]
for (int i = sz - 1; i >= 0; --i) {
dfs(ve[u][i], d + 1);
}
}
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; ++i) {
scanf("%d", &x);
// 因为i递增,对于每个pos ve[pos]存储的下标值,是从小到大的
ve[x+1].push_back(i);
}
value = n + 1;
k = n + 1;
dfs(n + 1, 0);
printf("%d\n", k);
for (int i = 1; i <= n; ++i) {
a[i] = 1LL * (deep[1] - deep[i]) * k + val[i];
printf("%lld\n", a[i]);
}
}