栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

Codeforces 1684D

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Codeforces 1684D

问题描述

有 n n n个陷阱,编号从 1 1 1到 n n n。你将按照顺序通过它们。第 i i i个陷阱对你提供 a i a_i ai​点基本伤害。

有时候你可以跳过一个陷阱而不是通过这个陷阱。你可以跳过不超过 k k k个陷阱。跳过的陷阱不会对你造成任何伤害,但是跳过的陷阱右边的陷阱的伤害都会自动加 1 1 1(附加伤害)。

如果你跳过一个陷阱,你不会得到任何伤害(包括基本伤害和附加伤害)。而且附加伤害是会递增的。举个例子,如果你跳过一个基本伤害为 a i a_i ai​的陷阱 i i i,而且你以前跳过了 3 3 3个陷阱,你将受到 ( a i + 3 ) (a_i+3) (ai​+3)点伤害。

你要求出在跳过不超过 k k k个陷阱的前提下你将得到的最少伤害。

输入格式

有多组测试数据。第一行为一个整数 t ( 1 ≤ t ≤ 100 ) t (1 le t le 100) t(1≤t≤100)表示测试数据组数。测试数据的描述如下。

第一行为两个整数 n n n和 k k k ( 1 ≤ n ≤ 2 ⋅ 1 0 5 , 1 ≤ k ≤ n ) (1 le n le 2 cdot 10^5,1 le k le n) (1≤n≤2⋅105,1≤k≤n),表示陷阱的数目和可以跳过的陷阱数目。

第二行为 n n n个整数 a 1 , a 2 , … , a n ( 1 ≤ a i ≤ 1 0 9 ) a_1,a_2,dots,a_n (1 le a_i le 10^9) a1​,a2​,…,an​(1≤ai​≤109)表示每个陷阱的基本伤害。

所有测试数据的 n n n之和不会超过 2 ⋅ 1 0 5 2 cdot 10^5 2⋅105。

输出格式

对所有测试数据,输出一个整数表示在跳过不超过 k k k个陷阱的前提下你将得到的最少伤害。

输入输出样例
输入输出
5
4 4
8 7 1 4
4 1
5 10 11 5
7 5
8 2 5 15 11 2 8
6 3
1 2 3 4 5 6
1 1
7
0
21
9
6
0
样例解释

第一个测试数据,可以跳过所有陷阱,造成 0 0 0点伤害。

第二个测试数据,有 5 5 5种方法跳过陷阱:

1.不跳过任何陷阱。

总伤害: 5 + 10 + 11 + 5 = 31 5+10+11+5=31 5+10+11+5=31。

2.只跳过第一个陷阱。

总伤害: 0 + ( 10 + 1 ) + ( 11 + 1 ) + ( 5 + 1 ) = 29 0+(10+1)+(11+1)+(5+1)=29 0+(10+1)+(11+1)+(5+1)=29。

3.只跳过第二个陷阱。

总伤害: 5 + 0 + ( 11 + 1 ) + ( 5 + 1 ) = 23 5+0+(11+1)+(5+1)=23 5+0+(11+1)+(5+1)=23。

4.只跳过第三个陷阱。

总伤害: 5 + 10 + 0 + ( 5 + 1 ) = 21 5+10+0+(5+1)=21 5+10+0+(5+1)=21。

5.只跳过第四个陷阱。

总伤害: 5 + 10 + 11 + 0 = 26 5+10+11+0=26 5+10+11+0=26。

为得到最小的伤害,需要跳过第三个陷阱,所以答案是 21 21 21。

第三个测试数据,跳过陷阱的最优解是 1 , 3 , 4 , 5 , 7 1,3,4,5,7 1,3,4,5,7。

总伤害: 0 + ( 2 + 1 ) + 0 + 0 + 0 + ( 2 + 4 ) + 0 = 9 0+(2+1)+0+0+0+(2+4)+0=9 0+(2+1)+0+0+0+(2+4)+0=9。

题解

易知,跳过陷阱的顺序和解无关。

因此,结论就非常简单了。

跳过收益最大的几个点。

每个点的收益,可以按照以下的规则计算。

假定有三个点 a a a, b b b, c c c,所处位置为 1 1 1, 2 2 2, 3 3 3

正序跳过的解是这样的:跳过1的收益是 a − 2 a-2 a−2,数组变成 b + 1 b+1 b+1, c + 1 c+1 c+1

再跳过 b + 1 b+1 b+1的收益是 b b b,数组变成 c + 2 c+2 c+2

再跳过 c + 2 c+2 c+2,可过。

反向跳过其实也一样。

a − 2 + b − 1 + c + 3 = a + b + c a-2+b-1+c+3=a+b+c a−2+b−1+c+3=a+b+c

3 = ( 1 + 2 ) × 2 ÷ 2 3=(1+2) times 2 div 2 3=(1+2)×2÷2

类似地, k ( k − 1 ) 2 frac{k(k-1)}{2} 2k(k−1)​为单纯加上收益后的补充。

代码如下:

#include 
using namespace std;
long long a[200001],s[200001];
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		long long n,k,ans=0;
		scanf("%lld%lld",&n,&k);
		for(int i=1;i<=n;i++) scanf("%lld",&a[i]),s[i]=a[i]-n+i,ans+=a[i];
		ans-=k*(k-1)/2;
		sort(s+1,s+n+1);
		for(int i=n;i>=n-k+1;i--) ans-=s[i];
		printf("%lldn",ans);		
	}
	return 0;
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/947651.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号