Codeforces div 863C

文章详细阐述了一个编程问题,即如何从数组b还原出数组a,其中b由a的相邻元素的最大值构成。两种解法被提出,一种是直接使用min操作,另一种是通过比较相邻元素的大小关系来重建a数组。这两种方法在特定条件下都能保证a数组的合法性。
摘要由CSDN通过智能技术生成

Problem - C - Codeforces

设定m=n-1

首先,对于a数组的开头与末尾,我们可以证明,他总是等于b数组的开头和结尾

因为如果 a 2 > a 1 a_2>a_1 a2>a1 那么 a 1 a_1 a1也就无法被还原了,所有 { x ∣ x ≤ a 2 } \{x| x\leq a_2\} {xxa2}都是成立的,而此时 b 1 b_1 b1是等于 a 2 a_2 a2的,也就保证了 a 1 a_1 a1一定可以等于 b 1 b_1 b1

同理, a n = b m a_n =b_m an=bm

解法一

对于b数组中的每个数字,是由a数组中左右两个数字取较大值得到的,通过对 a 1 = b 1 a_1 = b_1 a1=b1 a n = b n − 1 a_n = b_n-1 an=bn1 a i = m i n ( b i , b i − 1 ) a_i = min(b_i,b_{i-1}) ai=min(bi,bi1)的实现课复原一个合法的a数组

具体原理如下

考虑一个 1 < i < n 1<i<n 1<i<n a i a_i ai

b i = m a x ( a i , a i − 1 ) b_i = max(a_i,a_{i-1}) bi=max(ai,ai1) b i + 1 = m a x ( a i , a i + 1 ) b_{i+1} = max(a_i,a_i+1) bi+1=max(ai,ai+1)是成立的

我们考虑这样一种情况,也就是 b i , b i − 1 b_i,b_{i-1} bi,bi1均不是a_i原值的时候,即 a i − 1 < a i < a i + 1 a_{i-1} < a_i<a_{i+1} ai1<ai<ai+1,此时 a i a_i ai 无法被还原,也就是说 a i = m i n ( a i − 1 , a i + 1 ) a_i = min(a_{i-1},a_{i+1}) ai=min(ai1,ai+1),即 a i = m i n ( b i , b i − 1 ) a_i = min(b_i,b_{i-1}) ai=min(bi,bi1)

对于其他情况,如 b i = = a i ∣ ∣ b i − 1 = = a i b_i==a_i||b_{i-1} ==a_i bi==ai∣∣bi1==ai, 我们直接取两个值当中的最小值就好。因为通过分析可以发现,原来的值一定为较小值

a i − 1 < a i < a i + 1 a_{i-1} < a_i< a_i+1 ai1<ai<ai+1 b i = a i b_i = a_i bi=ai b i + 1 = a i + 1 b_{i+1} = a_{i+1} bi+1=ai+1 由于 a i < a i + 1 a_i<a_{i+1} ai<ai+1所以 a i a_i ai为其中较小值

由于对称,所以相反的状况下该结论也成立

对于 a i a_i ai在三个值中最大的情况也是成立的因为 b i = b i − 1 = a i b_i=b_i-1 = a_i bi=bi1=ai

所以,对它使用结论吧

inline void slove()
{
    cin >> n;
    m = n - 1;

    for (int i = 1; i <= m; i++) cin >> b[i];

    a[n] = b[m];
    a[1] = b[1];
    for (int i = m; i>1; i--)
        a[i] = min(b[i - 1], b[i]);

    for (int i = 1; i <= n; i++) printf("%lld ", a[i]);
    puts("");

    return;
} 

解法二
其实解法二是对解法一的近似,两者是完全相同的,只不过一个用到了min,另一个没有,不过由于思路的完全不同,这里还是讲一下

从尾遍历,对于每一个 b i b_i bi,如果出现 b i > b i − 1 b_i>b_{i-1} bi>bi1的情况,需要重复一遍 b i b_i bi,再添加 b i − 1 b_{i-1} bi1

inline void slove()
{
    cin >> n;
    m = n - 1;

    for (int i = 1; i <= m; i++) cin >> b[i];

    a[n] = b[m];
    a[1] = b[1];
    for (int i = m; i > 1; i--)
    {
        if (b[i - 1] > b[i])
        {
            a[i] = b[i];
            a[i - 1] = b[i - 1];
        }
        else a[i] = b[i - 1];
    }

    for (int i = 1; i <= n; i++) printf("%lld ", a[i]);
    puts("");

    return;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值