洛谷P7917 【洛谷月赛LGR-096 Div.2 T1】 [Kubic] Addition题解

一题贪心算法解析
本文解析了一道关于贪心算法的题目,通过分析每个数对答案的贡献,提出了解决方案并给出了代码实现。

这道题真是让我深刻地陷入了对我智商的怀疑。。。比赛想了50min,结果最后评出来难度是
在这里插入图片描述
过分了啊。。。

题目大意

在这里插入图片描述

解题思路

贪心。
可以看出,每个数aia_iai对答案的贡献是±ai\pm a_i±ai。(因为它要么被减,要么被加。)那么我们尽量让每个数的贡献为其绝对值。又注意到a1a_1a1的贡献永远是a1a_1a1本身(因为没有哪个数能减它)。那么,最优解就是a1+∑i=2n∣ai∣a_1+\sum \limits_{i=2}^n|a_i|a1+i=2nai
下面证明最优解一定可以构造出来。考虑从右往左合并,对于当前数aia_iai和合并其右边的数已经得到的数±∑j=i+1n∣aj∣\pm \sum \limits_{j=i+1}^n|a_j|±j=i+1naj,若aia_iai±∑j=i+1n∣aj∣\pm \sum \limits_{j=i+1}^n|a_j|±j=i+1naj同号,则执行x+yx+yx+y,否则执行x−yx-yxy,使得后iii个数得到的和为±∑j=in∣aj∣\pm \sum \limits_{j=i}^n|a_j|±j=inaj。最终答案就是a1+∑i=2n∣ai∣a_1+\sum \limits_{i=2}^n|a_i|a1+i=2nai
时间复杂度:O(n)O(n)O(n)

奉上高清无码Code:

#include <cstdio>
#include <cstdlib>
#include <cctype>

using namespace std;

typedef long long ll;

ll n;

inline ll read() // 快速读入
{
    ll ret = 0;
    char sgn = 0;
    char c;
    while(!isdigit(c = getchar())) if(c == '-') sgn = 1;
    ret = c ^ 48;
    while(isdigit(c = getchar())) ret = (ret << 1) + (ret << 3) + (c ^ 48);
    return sgn ? -ret : ret;
}

int main()
{
    n = read();
    ll ans = read(); // ans = a[1]
    while(--n) ans += llabs(read());
    // ans += |a[2]| + |a[3]| + ... + |a[n]|
    printf("%lld\n", ans);
    return 0;
}

如果还不理解的话,举个栗子:

5
-1 2 -3 4 -5

4−(−5)→(−1,2,−3,9)4-(-5)\to(-1,2,-3,9)4(5)(1,2,3,9)
−3−9→(−1,2,−12)-3-9\to(-1,2,-12)39(1,2,12)
2−(−12)→−1,142-(-12)\to-1,142(12)1,14
−1+14→13-1+14\to131+1413
答案就是13=−1+∣2∣+∣−3∣+∣4∣+∣−5∣=a1+∑i=2n∣ai∣13=-1+|2|+|-3|+|4|+|-5|=a_1+\sum \limits_{i=2}^n|a_i|13=1+2+3+4+5=a1+i=2nai

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值