思路 :
因为bi的值就1 和 2 , 所以预先把bi值为1对应的ai分到一组al , bi值为2对应的ai分到一组bl,再从大到小排列, 接着对bl进行前缀和处理 , 记为pre , 然后对al进行for循环 ,循环中进行二分处理就行了 , 记录每种情况对应的ans , 最小值即为答案 。
比赛的时候思路不对 , 吃下了没文化的苦果 /(ㄒoㄒ)/~~
代码 :
#include<bits/stdc++.h>
using namespace std ;
typedef long long ll ;
const int maxn = 2e5 + 10 ;
const ll inf = 0x3f3f3f3f ;
ll t , n , m , a[maxn] , b[maxn] , al[maxn] , bl[maxn] ;
ll pre[maxn] ;
int main(){
ios::sync_with_stdio(false) ;
cin.tie(0) ;
cout.tie(0) ;
int t ;
cin >> t ;
while(t--){
cin >> n >> m ;
for(int i = 1 ; i <= n ; i++) cin >> a[i] ;
for(int i = 1 ; i <= n ; i++) cin >> b[i] ;
ll cnta = 0 , cntb = 0 ;
for(int i = 1 ; i <= n ; i++){
if(b[i] == 1) al[++cnta] = a[i] ; //存b[i]值为1对应的a[i]
else bl[++cntb] = a[i] ; //存b[i]值为2对应的a[i]
}
sort(al + 1 , al + 1 + cnta , greater<int>()) ; //从大到小排列
sort(bl + 1 , bl + 1 + cntb , greater<int>()) ;
memset(pre , 0 , sizeof(pre)) ;
for(int i = 1 ; i <= cntb ; i++) pre[i] = pre[i-1] + bl[i] ; //前缀和处理
ll ans = inf , sum = 0 ;
for(ll i = 1 ; i <= cnta ; i++){
sum += al[i] ;
if(sum >= m){ //情况讨论完了 退出
ans = min(i , ans) ;
break ;
}
ll temp = m - sum ; //剩下多少
ll index = lower_bound(pre + 1 , pre + 1 + cntb , temp) - pre ;
if(index == cntb + 1) continue ; //如果没有查询到 , 返回数组最后一个元素的下一个元素
ans = min(ans , i + index * 2) ;
}
ll index = lower_bound(pre + 1 , pre + 1 + cntb , m) - pre ;
if(index != cntb + 1) ans = min(ans , index * 2) ; //同上
if(ans == inf) cout << -1 << endl ;
else cout << ans << endl ;
}
}