D. Cleaning the Phone(Codeforces Round #697 (Div. 3)题解)

题目链接:D. Cleaning the Phone
思路:考虑先将物品按价值排好,然后我们从高向低拿,一旦有拿大于等于m价值的东西,我们就停止。这时候发现如果我们的物品体积都是1的话,现在肯定是最优的答案,现在拿的物品体积一定是最优的。当我们考虑到有体积为2的物品存在时,我们现在肯定是选择某些体积为1的商品去替换我们曾经选过的体积为2的商品(再继续拿体积为2的商品就没有意义了),这时候我们就开始遍历剩下的体积为1的商品。设\(sum\)为当前选择物品的总价值,a数组表示每件物品的价值,\(val\)表示当前已经选择的且体积为2的物品中价值最小的一件,我们会发现产生以下2种情况:

  1. \(sum - val + a_i>=m\)说明用当前这件体积为1的物品可以替换体积为2的物品。
  2. \(sum - val + a_i<m\)\(val<=a_i + a_{i+1}\)这时候说明我们选择现在最大的两件物品,总价值优于我们选择一件体积为2的物品,这时候我们肯定选择这两件物品,因为这能在体积不变的前提下,使价值更高,这说明下面再进行时我们可以替换更多的物品。
    最后维护的便是答案了。
    \(Code:\)

#include<set>
#include<iostream>
#include<cstring>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<map>
#include<algorithm>
#include<vector>
#include<queue>
#define ch() getchar()
#define pc(x) putchar(x)
#include<stack>
#include<unordered_map>
#define rep(i,a,b) for(auto i=a;i<=b;++i)
#define bep(i,a,b) for(auto i=a;i>=b;--i)
#define lowbit(x) x&(-x)
#define ll long long
#define ull unsigned long long
#define pb emplace_back
#define mp make_pair
#define PI acos(-1)
using namespace std;
template<typename T>void read(T&x){
    static char c;
    static int f;
    for(c=ch(),f=1; c<'0'||c>'9'; c=ch())if(c=='-')f=-f;
    for(x=0; c>='0'&&c<='9'; c=ch())x=x*10+(c&15);
    x*=f;
}
template<typename T>void write(T x){
    static char q[65];
    int cnt=0;
    if(x<0)pc('-'),x=-x;
    q[++cnt]=x%10,x/=10;
    while(x)
        q[++cnt]=x%10,x/=10;
    while(cnt)pc(q[cnt--]+'0');
}

const int N = 2e5+10;
int _,n;ll m,c[N];
struct node{
    ll a;
    int b;
    bool operator<(node &c)const{
        return c.a<a;
    }
}a[N];
ll pop[N],tot,cur[N];
void solve(){
    read(_);
    while(_--){
        tot = 0;
        read(n);read(m);
        rep(i,1,n)read(c[i]);
        int x;
        rep(i,1,n)read(x),a[i] = {c[i],x};
        sort(a+1,a+1+n);
        ll sum = 0ll;int ans = 0;
        int idx = n+1;
        rep(i,1,n){
            sum += a[i].a;
            ans += a[i].b;
            if(a[i].b == 2){pop[++tot] = i; }
            if(sum >= m){idx = i+1;break; }
        }
        if(sum < m)ans = -1;
        else {
        int tt = 0;
        rep(i,idx,n){
            if(a[i].b == 2)continue;
            cur[++tt] = a[i].a;
        }
        rep(i,1,tt){
            if(!tot)break;
            ll now = a[pop[tot]].a;
            if(sum - now + cur[i]>=m){
                sum = sum - now + cur[i];
                ans--;tot--;
            }
            else {
                if(i!=tt){
                    if(now<=cur[i] + cur[i+1]){
                        sum -= now;
                        sum += cur[i] + cur[i+1];
                        tot--;i++;
                    }
                }
            }
        }
        }
        write(ans);pc('\n');
    }
}


signed main(){solve();return 0; }



posted @ 2021-05-27 15:08  xiaodangao  阅读(51)  评论(0编辑  收藏  举报