P5078 Tweetuzki 爱军训

Tweetuzki 爱军训

引言

本文更注重推导过程,无法理解其他题解的可以来这里看看。

解法

考虑贪心。

ans 表示最后的答案,在刚开始时假设全部都按 1n 的顺序出列,则 ans=i=1nwi×i

对第 k 个同学出列的价值变化考虑,有:

ans=i=1k1wi×i+k+1nwi×(i1)+n×wk

我们计算初始的 ans 和变化后的 ans 值的差值:

delta=i=1nwi×i(i=1k1wi×i+k+1nwi×(i1)+n×wk)

=i=1nwi×ii=1k1wi×ik+1nwi×(i1)n×wk

=i=knwi×ii=k+1nwi×i+k+1nwin×wk

=(kn)×wkk+1nwi

我们设 prem=i=1mwi

则:

delta=(kn)×wk(prenprek)

如果 delta<0,则说明第 k 位上同学在教官反着走的时候出列,比在教官正着走时出列更优,则使得第 k 为上的人出列即可。

那么我们的核心代码就很好写了:

for(int k = 1;k <= n;k++){
    if(pre[n] - pre[k] + (k - n) * w[k] < 0){
        ans += -(pre[n] - pre[k] + (k - n) * w[k]);
        id[k] = true;
	}
}

证明

我们推导的时候会发现,有没有可能选择一个 k 位置上的人,反着走时被选择,会对其他人的选择贪心判断造成影响。

考虑在我们想要选择 k 位置上的人时,前面已经有一个 s 位置上的人被选了。(k>s

则选择这两个后的 ans 会变为:

i=1s1wi×i+i=s+1k1wi×(i1)+i=k+1nwi×(i2)+ws×n+wk×(n1)

那么 delta 会变为:

i=1nwi×i(i=1s1wi×i+i=s+1k1wi×(i1)+i=k+1nwi×(i2)+ws×n+wk×(n1))

=i=snwi×ii=s+1k1wi×(i1)i=k+1nwi×(i2)ws×nwk×(n1)

=i=snwi×ii=s+1k1wi×i+i=s+1k1wii=k+1nwi×i+i=k+1n2wiws×nwk×n+wk

=(i=knwi×i+ws×s)+(prek1pres)i=k+1nwii+2×(prenprek)ws×nwk×n+wk

=wk×(kn)+ws×(kn)+(prenprek)+(prenpres)+wk(prek1prek)

={(kn)×wk(prenprek)}+{(sn)×ws(prenpres)}

那么我们发现,最后的式子可以拆成 s 单独选择和 k 单独选择后加起来。

同理可得,无论多少个数选择都不会对彼此造成影响,也就是说这些选择彼此是独立的。

那么贪心即可,代码超短:

#include <iostream>
#include <algorithm>
using namespace std;
#define int long long
const int MAXN = 1e6 + 7;
int n;
int w[MAXN];
bool id[MAXN];
int pre[MAXN];
int ans;
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cin >> n;
    for(int i = 1;i <= n;i++) cin >> w[i],pre[i] = pre[i - 1] + w[i];
    for(int i = 1;i <= n;i++) pre[i] = pre[i - 1] + w[i],ans += w[i] * i;
    for(int k = 1;k <= n;k++){
        if(pre[n] - pre[k] + (k - n) * w[k] < 0){
            ans += -(pre[n] - pre[k] + (k - n) * w[k]);
            id[k] = true;
        }
    }
    cout << ans << endl;
    for(int i = 1;i <= n;i++) if(!id[i]) cout << w[i] << " ";
    for(int i = n;i >= 1;i--) if(id[i]) cout << w[i] << " "; 
    return 0;
}

done.

posted @   wyl123ly  阅读(11)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
历史上的今天:
2023-10-10 最短路
2023-10-10 p4801题解
点击右上角即可分享
微信分享提示