CF1475D. 清理电话

CF1475D. 清理电话

原题链接

描述

存在一个数组,每个元素有两个属性 \(a\)\(b\),要求从中选出一些值,\(\sum a>=m\),且 \(\sum b\) 最小,求 \(\sum b\) 最小值。

思路

由于 b 只有1 2 两个值,可以用两个数组分别存 b 属性为 1 和 2 的值,并将其从大到小排序。则要求 \(\sum b\) 最小,就是求这两个数组的前缀。用双指针枚举前缀即可。

代码

#include <bits/stdc++.h>
using namespace std;
int main(){
    int t; cin>>t; while(t--){
        int n,m; cin>>n>>m;
        vector<int> a(n);
        vector<int> arr1,arr2;
        for(int i=0;i<n;i++) scanf("%d",&a[i]);
        for(int i=0;i<n;i++){
            int b; scanf("%d",&b);
            if(b==1) arr1.push_back(a[i]);
            else arr2.push_back(a[i]);
        }
        sort(arr1.rbegin(),arr1.rend());
        sort(arr2.rbegin(),arr2.rend());
        int len1=arr1.size(),len2=arr2.size();
        long long s=0;
        int i=0,j=0;
        for(j=0;j<len2;j++){
            s+=arr2[j]; if( s>=m||j==len2-1) break;
        }
        int ans=0x3f3f3f3f;
        if(len2==0) j=-1;
        if(s>=m)
            ans=(j+1)*2;;
        for(i=0;i<len1;i++){
            s+=arr1[i];
            while(j>=0&&s-arr2[j]>=m){
                s-=arr2[j]; j--; 
            }
            if(s>=m)
                ans=min(ans,(i+1)+(j+1)*2);
        }
        if(s<m) puts("-1");
        else cout<<ans<<endl;
    }
    return 0;
}
posted @ 2021-01-26 20:49  ans20xx  阅读(51)  评论(0编辑  收藏  举报