http://codeforces.com/problemset/problem/285/C Building Permutation

排序后将从小到达往1-n去进行所谓的归位,如何证明这个是最优的呢。
该贪心算法可以做如下描述:
A是一个长度为n的从小到大排序的序列a1 <= a2 <= a3 <= … <= an,初始时集合S为空,每一次贪心选择A中最小的,且未加入集合S的下标k,将其归位到|S| + 1的位置,得到权值abs(a[k] - k),将k加入到S中。
下面利用Exchange Argument方法证明:
1.假定上述是贪心算法A的描述
2.假设O是与A最相似的最优算法(O和A的前k个选择相同,第k+1个开始不同)
3.A中第k个选择是(k,ak),O中第k个选择是(k,aj),ak <= aj,现在构造O‘ = O - (k,aj) + (k,ak),实际上相当于将第k个选择变成与A相同,而此时必定与O中第k选择后的一个选择p做一个交换。
4.因为O’使得对于1-n都有一个数归位到其位置,所以O’是正确的。
其次,对于O’,O而言,前k个选择贡献的权值是相同的,产生不同的权值和的原因在于后k个选择,因为O’仅在O的选择基础上交换了第k个选择和第p个选择(k <= p),于是只需考虑这两个选择产生的不同权值和,我们假定第p个选择中O的选择是(p,ak),由A中的选择可以知道ak <= aj,因为ax必定在A的第k个选择之后。于是O对于这两个选择产生的权值和为s1 = abs(ak - p) + abs(aj - k),O’对于两个选择产生的权值和为s2 = abs(aj - p) + abs(ak - k),因为p >= k,aj >= ak,我们分五种情况讨论1.aj >= ak >p>k,2.aj > p >= ak >= k,3.p >= aj >= ak >= k,4.p >= aj >= k > ak,5.p >= k > aj >= ak。
1:s1 - s2 = 0 s1 >= s2
2.s1 - s2 = p - ak + aj - k - aj + p - ak + k = 2p - 2ak >= 0 s1 >= s2
3.s1 - s2 = p - ak + aj - k - p + aj - ak + k = 2aj - 2ak >= 0 s1 >= s2
4.s1 - s2 = p - ak + aj - k - p + aj - k + ak = 2aj - 2k >= 0 s1 >= s2
5.s1 - s2 = p - ak + k - aj - p + aj - k + ak = 0 s1 >= s2
综上,s1>=s2,于是O’是一个比O更优的解,而O’与A更接近且它和接近的部分有K个,而O只有K-1个,于是A是最优的。

#include <iostream>
#include <string>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <stack>
#include <queue>
#define MAX 100005
#define mod 998244353ll
#define INF 0x3f3f3f3f
#define ll long long
using namespace std;
int a[300005];
int main() {
    freopen("a.txt", "r", stdin);
    freopen("b.txt", "w", stdout);
    int n;
    cin >> n;
    for (int i = 1; i <= n; ++i) {
        scanf("%d", &a[i]);
    }
    sort(a + 1, a + n + 1);
    ll s = 0;
    for (int i = 1; i <= n; ++i) {
        s = s + abs(a[i] - i);
    }
    cout << s << endl;
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值