题目链接:传送门
题目大意:
DG在书店买书,从左到右第i本书价格为ai。DG从左走到右,能买就买。如果已知DG买了m本书,问他原本最多有多少钱。若无上限,输出“Richman”,若不可能买这么多书,输出“Impossible”。
(偷偷diss队友想了个假二分)
1 ≤ n ≤ 105,0 ≤ m ≤ n,0 ≤ ai ≤ 109。
思路:
①:所有的价格为0的书DG必买,m -= cnt0。(这时若 m < 0,那就Impossible了)
②:DG从左走到右买书时,他在持有金额最多的情况下买的书只能是前面的m本书。
反证:假设DG已经买掉了钱m-1本书,接着如果他买不起第m本书,而买了第m+1本书,那么am > am+1,而在DG买得起第m本书的时候他会更有钱,这与持有金额最多的条件矛盾。
综上:DG最多的金额是前m本非0的书的总价格+剩下的非0的书中的价格最小值-1。
代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn=1e5+10; int n,m; ll a[maxn]; int judge(ll k) { int res=0; for(int i=1;i<=n;i++) { if(k>=a[i]) res++, k-=a[i]; } return res; } int main() { int T; cin>>T; while(T--) { scanf("%d%d",&n,&m); int cnt0=0; for(int i=1;i<=n;i++) { scanf("%lld",&a[i]); if(a[i]==0) cnt0++; } if(n<=m) { printf("Richman "); continue; } if(cnt0>m) { printf("Impossible "); continue; } m -= cnt0; ll ans=0; int i; for (i = 1; i <= n; i++) { if (m == 0) break; if (a[i] == 0) continue; ans += a[i]; m--; } ll mn=0x3f3f3f3f; for(;i<=n;i++) if(a[i]!=0) mn=min(mn,a[i]); printf("%lld ",ans+mn-1); } } /* 444 4 2 1 2 4 8 4 0 100 99 98 97 2 2 10000 10000 5 3 0 0 0 0 1 4 1 4 1 3 2 4 2 100 99 0 0 */