首页 > 其他分享 >P5078 Tweetuzki 爱军训

P5078 Tweetuzki 爱军训

时间:2024-10-10 21:03:41浏览次数:9  
标签:pre P5078 int sum ans times delta Tweetuzki 军训

Tweetuzki 爱军训

引言

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

解法

考虑贪心。

用 \(ans\) 表示最后的答案,在刚开始时假设全部都按 \(1 \to n\) 的顺序出列,则 \(ans = \sum^{n}_{i = 1} w_i \times i\)。

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

\[ans = \sum^{k - 1}_{i = 1} w_i \times i + \sum^{n}_{k + 1} w_i \times (i - 1) + n \times w_k \]

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

\[delta = \sum^{n}_{i = 1} w_i \times i - \left( \sum^{k - 1}_{i = 1} w_i \times i + \sum^{n}_{k + 1} w_i \times (i - 1) + n \times w_k \right) \]

\[= \sum^{n}_{i = 1} w_i \times i - \sum^{k - 1}_{i = 1} w_i \times i - \sum^{n}_{k + 1} w_i \times (i - 1) - n \times w_k \]

\[= \sum^{n}_{i = k} w_i \times i - \sum^{n}_{i = k + 1} w_i \times i + \sum^{n}_{k + 1} w_i - n \times w_k \]

\[= (k - n) \times w_k - \sum^{n}_{k + 1} w_i \times i \]

我们设 \(pre_m = \sum^{m}_{i = 1}w_i\)

则:

\[delta = (k - n) \times w_k - (pre_n - pre_k) \]

如果 \(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\) 位置上的人,反着走时被选择,会对其他人的\times\times选择贪心判断\times\times造成影响。

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

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

\[\sum^{s - 1}_{i = 1}w_i \times i + \sum^{k - 1}_{i = s + 1} w_i \times (i - 1) + \sum^{n}_{i = k + 1}w_i \times (i - 2) + w_s \times n + w_k \times (n - 1) \]

那么 \(delta\) 会变为:

\[\sum^{n}_{i = 1} w_i \times i - \left(\sum^{s - 1}_{i = 1}w_i \times i + \sum^{k - 1}_{i = s + 1} w_i \times (i - 1) + \sum^{n}_{i = k + 1}w_i \times (i - 2) + w_s \times n + w_k \times (n - 1)\right) \]

\[= \sum^{n}_{i = s} w_i \times i - \sum^{k - 1}_{i = s + 1} w_i \times (i - 1) - \sum^{n}_{i = k + 1} w_i \times (i - 2) - w_s \times n - w_k \times(n - 1) \]

\[= \sum^{n}_{i = s} w_i \times i - \sum^{k - 1}_{i = s + 1} w_i \times i + \sum^{k - 1}_{i = s + 1}w_i - \sum^{n}_{i = k + 1} w_i \times i + \sum^{n}_{i = k + 1}2w_i - w_s \times n - w_k \times n + w_k \]

\[= \left( \sum^{n}_{i = k} w_i \times i + w_s \times s \right) + (pre_{k - 1} - pre_s) - \sum^{n}_{i = k + 1}w_i * i + 2 \times (pre_n - pre_k) - w_s \times n - w_k \times n + w_k \]

\[= w_k \times (k - n) + w_s \times (k - n) + (pre_n - pre_k) + (pre_n - pre_s) + w_k - (pre_{k - 1} - pre_k) \]

\[= \{ (k - n) \times w_k - (pre_n - pre_k) \} + \{ (s - n) \times w_s - (pre_n - pre_s) \} \]

那么我们发现,最后的式子可以拆成 \(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.

标签:pre,P5078,int,sum,ans,times,delta,Tweetuzki,军训
From: https://www.cnblogs.com/wyl123ly/p/18457120

相关文章

  • 2024 JZ军训游记
    2024JZ军训游记在这次的军训中,你将会看到:主任力荐“JZ90周年校庆限定的水”、校长的殷切期望“希望你们中有一个人给JZ捐一个亿”、擒敌拳班的诈骗“室内空调”、“zbr——《我和教官的()故事》”、“czh和床的故事”、“酗宝矿力趁年华”等等。Day0搬东西到JZ,因为是信息学学......
  • <DFS剪枝>数字王国之军训排队
    其实就是将搜索过程一些不必要的部分直接剔除掉。剪枝是回溯法的一种重要优化手段,往往需要先写一个暴力搜索,然后找到某些特殊的数学关系,或者逻辑关系,通过它们的约>束让搜索树尽可能浅而小,从而达到降低时间复杂度的目的。示例:分析:n->[1,10],数据范围并不是很大,我们可以......
  • 入职军训中期心得
    有一段时间没有写过博客了,记得最一开始写博客还是在年级主任的威逼利诱之下被迫写的,最后也没有养成一定的习惯。回想那段学生时间,仿佛还在眼前,感觉还是学生时代比较幸福,不用考虑那么多事情,也不用考虑生活和吃饭的问题。如今我也算是正式的步入社会了,最近刚入职某汽车公司,然后入职......
  • P5080 Tweetuzki 爱序列 题解
    题目传送门更好地阅读体验题目大意Tweetuzki有一个长度为\(n\)的序列\(a_1,a_2,\cdots,a_n\)。他希望找出一个最大的\(k\),满足在原序列中存在一些数\(b_1,b......