Tests for Haybales(思维/dfs/构造)

题目
题意:已知一个长度为 n ( 1 < = n < = 1 0 5 ) n(1<=n<=10^5) n1<=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]);
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值