D. Cleaning the Phone 二分

题意:给出n个数,这些数代表的是所占用的内存

   每一个内存都有一个重要值;

   给定一个值m,让我们在重要值消耗最少的情况下,至少腾出m内存

   求此重要值

思路:二分

   题目给出的重要值,只有1跟2,所以可以把1跟2分别置于不同的数组,并且将每个数组按从大到小排序

   然后直接跑二分。

   二分check部分,从小到达枚举其中一个数组(另外一个可以通过m值跟枚举的数组推出来)即可(复杂度为n)

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const int maxn=2e5+10;
 5 ll a[maxn];
 6 ll b[maxn];
 7 ll tmp1[maxn];
 8 ll tmp2[maxn];
 9 ll sum1[maxn];
10 ll sum2[maxn];
11 int num1=0;
12 int num2=0;
13 int n,m;
14 bool cmp1(ll x,ll y)
15 {
16     return x>y;
17 }
18 bool cmp2(ll x,ll y)
19 {
20     return x>y;
21 }
22 ll mnn(ll x,ll y)
23 {
24     if(x<y) return x;
25     else return y;
26 }
27 int check(ll mid)
28 {
29     ll ans=0;
30     for(int i=1;i<=mnn(mid,num1);i++){
31         ll res=0;
32         res+=sum1[i];
33         ll tmp=(mid-i)/2;
34         if(tmp>=num2) tmp=num2;
35         res+=sum2[tmp];
36         ans=max(ans,res);
37     }
38     for(int i=1;i<=num2;i++){
39         if(2*i>mid) break;
40         ll res=0;
41         res+=sum2[i];
42         ll tmp=mid-i*2;
43         if(tmp>num1) tmp=num1;
44         res+=sum1[tmp];
45         ans=max(ans,res);
46     }
47     if(ans>=m) return 1;
48     else return 0;
49 }
50 int main()
51 {
52     int T;
53     scanf("%d",&T);
54     while(T--){
55         scanf("%d%d",&n,&m);
56         ll tmpsum=0;
57         for(int i=1;i<=n;i++){
58             scanf("%lld",&a[i]);
59             tmpsum+=a[i];
60         }
61         ll tmpr=0;
62         num1=num2=0;
63         for(int i=1;i<=n;i++){
64             scanf("%lld",&b[i]);
65             tmpr+=b[i];
66             if(b[i]==1) tmp1[++num1]=a[i];
67             else tmp2[++num2]=a[i];
68         }
69         if(tmpsum<m) printf("-1\n");
70         else{
71             sort(tmp1+1,tmp1+1+num1,cmp1);
72             sort(tmp2+1,tmp2+1+num2,cmp2);
73             for(int i=1;i<=num1;i++){
74                 sum1[i]=sum1[i-1]+tmp1[i];
75             }
76             for(int i=1;i<=num2;i++){
77                 sum2[i]=sum2[i-1]+tmp2[i];
78             }
79             ll l=0,r=tmpr;
80             ll ans=-1;
81             while(l<=r){
82                 ll mid=l+r>>1;
83                 if(check(mid)){
84                     ans=mid;
85                     r=mid-1;
86                 }
87                 else{
88                     l=mid+1;
89                 }
90             }
91             printf("%lld\n",ans);
92         }
93     }
94     return 0;
95 }
View Code

 

posted @ 2021-01-28 12:35  古比  阅读(157)  评论(0编辑  收藏  举报