题意:给定一个长度为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;
}
}