补题 [NC252735] 修改后的和

1
2
3
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld

题目描述

牛牛面前有一个由 $n$ 个整数组成的数组 $A_1,A_2,…,A_n$。

牛牛打算对这个数组进行若干次操作。

每次操作牛牛可以选择 $A_1,A_2,…,A_n$ 中的任意一个非负整数,记所选数的下标为 $k$。然后牛牛会把 $A_k,A_{k+1},…,A_n$ 都减少 $A_k$。

牛牛想知道他对这个数组进行恰好 $m$ 次操作后,数组中所有数的和最少是多少。

输入描述

本题采用多组案例输入,第一行一个整数 $T$ 代表案例组数。

每组案例中,第一行输入两个空格分隔的整数 $n\ m$。

接下来一行输入 $n$ 个由空格分隔的整数代表:$A_1,A_2,…,A_n$。

保证:

$0 < n,m \leq 10^5$

$-10^6 \le A_i \le 10^6$

单个测试点中所有案例 $n$ 的和不超过 $2\times 10^5$

单组案例的 $A_1,A_2,…,A_n$ 中至少有一个非负整数

输出描述

对于每组案例,输出一行一个整数代表牛牛在进行恰好 $m$ 次操作之后数组中所有数的和的最少值。

输入

1
2
3
4
5
2
5 10000
-9 0 -3 -1 -10000
5 3
-10 4 9 -2 0

输出

1
2
-10013
-42

说明

第一组案例只能不断地选择 $A_2$ 所以总和不变。

第二组案例一组最优选择是 [$A_3,A_2,A_2$]

数组的变化是: [-10,4,9,-2,0] —> [-10,4,0,-11,-9] —> [-10,0,-4,-15,-13] —> [-10,0,-4,-15,-13] 第二组理论上更好的方案是选择 [$A_1,A_3,A_2$]

但是由于选择 $A_1$ 时其是负数,所以这组方案不可以选择。

题解

题目解析

一道贪心题,假设我们得到了数组 [1,3,-1,5,6,3] ,那么它们每一个位置可以提供的减少量可以另外开一个数组存,即 [1*6,3*5,0,5*3,6*2,3*1] 等于 [6,15,0,15,12,3] .

我们只需要找到依据 $m$ 找到相应个数的最大减少量即可解决此问题.

AC代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include <iostream>
#include <cstring>
#include <cmath>
#include <string>
#include <queue>
#include <vector>
#include <algorithm>
using namespace std;

#define endl "\n"
#define CIN_ ios::sync_with_stdio(0)
#define CIN cin.tie(0)
#define MAXN(size) const long long MAXN = size + 100
#define var(size) int p[size]{}
#define mem(name,value) memset(name,value,sizeof(name))
#define fa(a,n,p) for(int i=a;i<=n;i+=p)
#define fb(a,n,p) for(int i=a;i>=n;i-=p)
#define cin(length,var) for(int i=1;i<=length;i++) cin >> var[i]
typedef long long ll;

MAXN(1e5);

signed main(){
CIN;CIN_;
int T;
cin >> T;
while(T--){
vector<ll> p(MAXN);
ll n,m,ans=0;
cin >> n >> m;
fa(1,n,1){
cin >> p[i];
ans += p[i];
p[i] = p[i] * (n - i + 1);//每个位置可以提供的减少量
}
sort(p.begin()+1, p.begin()+1+n);//从小到大排一下
reverse(p.begin()+1, p.begin()+1+n);//反过来从大到小
fa(1,min(n,m),1){//取min(n,m)的原因是有可能m很大.
if(p[i] > 0){//大于零就可以减
ans -= p[i];
}
}
cout << ans << endl;
}
return 0;
}