题目
思路
我们可以先对商品的价值从小到大开始排序,当我要挑选k个价值不大于x的商品时,要达成最大的价值和,只需要从最后一个价值不大于x的商品往前累加,举个例子,假设排序后数组为1,2,3,4,5,k为2,x为3,那么最大价值和就是从3+2=5。当然如果k是4,最大价值和只能是3+2+1=6了。对于查找最后一个价值不大于x的商品,二分查找即可。对于累加,使用前缀和进行优化。
代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int maxn=1e5+5;
int arr[maxn],flag[maxn];
int arr2[maxn];
signed main(){
int n,q;cin>>n>>q;
for(int i=1;i<=n;i++){
cin>>arr[i];
}
sort(arr+1,arr+n+1);
for(int i=1;i<=n;i++){
arr2[i]=arr[i];
}
// for(int i=1;i<=n;i++)cout<<arr[i]<<" ";
// cout<<endl;
flag[n]=n;
for(int i=n-1;i>=1;i--){
if(arr[i]<arr[i+1])flag[i]=i;
else if(arr[i]==arr[i+1])flag[i]=flag[i+1];
}
for(int i=1;i<=n;i++){
arr2[i]+=arr2[i-1];
}
// for(int i=1;i<=n;i++)cout<<arr2[i]<<" ";
// cout<<endl;
while(q--){
int k,x;cin>>k>>x;
int l=1,r=n,idx=-1;
while(r>=l){
int mid=(l+r)/2;
if(arr[mid]<x){
l=mid+1;
}
else if(arr[mid]>x){
r=mid-1;
}
else if(arr[mid]==x){
idx=flag[mid];
break;
}
}
if(idx!=-1){
if(idx-k+1>=1)cout<<arr2[idx]-arr2[idx-k]<<endl;
else cout<<arr2[idx]<<endl;
}
else {
idx=flag[r];
if(idx-k+1>=1)cout<<arr2[idx]-arr2[idx-k]<<endl;
else cout<<arr2[idx]<<endl;
}
}
}