Codeforces Round #792 (Div. 1 + Div. 2) D

题意:给定一个长度为n的序列,你可以不选择k个数,但如果不选择这个数就会对后面选的每一个数伤害加1,问最终能选的最小的总和是多少。

思路:首先我们知道这个k个数一定是会被全部选的,白给你的便宜干嘛不收,大不了把k个数都放最后面也能减少答案。

接着,我们就可以开始选择k个数了。

假定我们选择的数的位置为p1,p2,p3.....p(k-1),pk;

则可以将答案分成k段

第一段:a[1]+....+a[p1-1];

第二段:a[p1+1]+...+a[p2-1]+(p2-p1-1)*1;

第三段:a[p2+1]+...+a[p3-1]+(p3-p2-1)*2;

第k段:a[pk+1]+.....+a[n]+(n-pk-1)*(k-1);

设sum=a[1]+a[2]+.....a[n]

前面这一段=sum-(a[p1]+a[p2]....+a[pk])

接着对于后面这一段分为两部分

一:p2-p1+2*p3-2*p2+3*p4-3*p3+......+k*n-k*pk

=-(p1+p2+p3+.....pk)+k*n;

二:-[1+2+3+......(k-1)]

=-(k*(k-1)/2)

然后全部加起来=sum-(a[p1]+a[p2]+...a[pk]+p1+p2+...pk)+kn-k*(k-1)/2

我们发现选择时会影响答案的只有a[i]+i,于是我们只要选出k个a[i]+i最大的位置减掉即可

代码:

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
#define pii pair<int,int>
int main(){
   long long t,a[N];
   cin>>t;
   while(t--){
   	 long long n,k;
   	 long long ans=0;
   	 cin>>n>>k;
   	 for(int i=1;i<=n;i++)cin>>a[i],ans+=a[i],a[i]=a[i]+i;
   	 ans-=1ll*k*(k-1)/2-1ll*n*k;
   	 sort(a+1,a+1+n);
   	 for(int i=n-k+1;i<=n;i++){
   	     ans-=a[i];	
	 }
	 cout<<ans<<endl;
   }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值