题目:有n个手机软件,每个有ai的空间与bi的便利度,问怎样删软件,可以至少删掉m的空间并且损失的便利度最小。
本来想找DP题练练的,结果这怎么看可以直接贪。
因为便利度只有2种,那么同样便利度里面只要选最大的空间就可以了。
所以分别按照便利度1 2存,然后大到小排序,尽可能的选取2然后再尝试用1替换2,一遍遍历下来一定能找到最优解。
下附代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<bits/stdc++.h> 2 #define ll long long 3 using namespace std; 4 const int INF=0X3f3f3f3f; 5 ll n,m,v[200005],a[200005],b[200005]; 6 bool cmp(ll x, ll y){ 7 return x>y; 8 } 9 int main(){ 10 int T; 11 scanf("%d",&T); 12 while (T--){ 13 scanf("%d%d",&n,&m); 14 int l1=0,l2=0; 15 for (int i=1; i<=n; i++){ 16 scanf("%d",&v[i]); 17 } 18 for (int i=1; i<=n; i++){ 19 int x; 20 scanf("%d",&x); 21 if (x==1){ 22 a[++l1]=v[i]; 23 } 24 else { 25 b[++l2]=v[i]; 26 } 27 } 28 sort(a+1,a+1+l1,cmp); 29 sort(b+1,b+1+l2,cmp); 30 ll sum=0,res=INF,j=1; 31 for (j=1; j<=l2; j++){ 32 sum+=b[j]; 33 if (sum>=m || j==l2) break; 34 } 35 if (l2==0) j=0; 36 if (sum>=m) res=j*2; 37 for (int i=1; i<=l1; i++){ 38 sum+=a[i]; 39 while (j>=1 && sum-b[j]>=m){ 40 sum-=b[j]; 41 j--; 42 } 43 if (sum>=m) res=min(res,i+j*2); 44 } 45 if (sum<m) printf("-1 "); 46 else printf("%lld ",res); 47 } 48 }