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种情况:
- \(sum - val + a_i>=m\)说明用当前这件体积为1的物品可以替换体积为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; }