题意
给你一个长度为n的数组,代表每一个物品的价格。你有一个初始钱数(x),采用以下方法贪心:
从(1)到(n)扫一遍,如果(x)不比(a[i])小,就买下它,买不起就跳过。
给你最终买的物品数量m,求(x)的最大值。
思路
我队的贪心菜的一笔,果然我也有很大的责任。。
首先如果最后全部买完,那么刚开始的钱一定是无穷多的。
我们先假设数组里没有0,那么通过题意中的贪心方法,最后买的一定是前m个。
证明:
当(m=0)的时候,显然成立。
假设当(m=i)的时候成立,即已经连续买了前(i)个。
买第(i+1)个的时候,如果不买(a[i+1]),而买了(a[j]),(j>i+1):
①当(a[i+1]leq a[j])时,由于题意中的贪心,如果买了(a[j]),对于(j>i+1),且(a[j]geq a[i+1])时,(a[i+1])是必买的,所以不成立
②当(a[i+1]>a[j])时,由于两个位置对m的贡献都为1,为使答案最大,还是要选最大的(a[i+1])
综上所述,此时要买(a[i+1])
再综上所述,最后买的一定是前m个
所以,没有0的时候,我们直接买前m个即可
当数组里是有0时,因为永远可以买0,所以要从m里减去0的个数,然后对剩下的数做上述算法
当然如果0的个数本身就超过(m),就是(impossible)的。
代码
注释提供了一些假算法的插点
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string>
#include<stack>
#include<queue>
#include<deque>
#include<set>
#include<vector>
#include<map>
#include<functional>
#define fst first
#define sc second
#define pb push_back
#define mem(a,b) memset(a,b,sizeof(a))
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define lc root<<1
#define rc root<<1|1
#define lowbit(x) ((x)&(-x))
using namespace std;
typedef double db;
typedef long double ldb;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> PI;
typedef pair<ll,ll> PLL;
const db eps = 1e-6;
const int mod = 1e9+7;
const int maxn = 3e6+100;
const int maxm = 2e6+100;
const int inf = 0x3f3f3f3f;
const db pi = acos(-1.0);
int n,m;
ll a[maxn];
int cnt;
ll sum[maxn];
multiset<ll>s;
int main() {
int t;
scanf("%d", &t);
while(t--){
cnt=0;
scanf("%d %d", &n, &m);
for(int i = 1; i <= n; i++){
scanf("%lld", &a[i]);
if(!a[i])cnt++;
}
if(n==m){
printf("Richman
");continue;
}
if(cnt>m){
printf("Impossible
");continue;
}
ll ans=0;
m-=cnt;
int p = 0;
int num=0;
for(int i = 1; i <= n&&num<m; i++){
if(a[i]){ans+=a[i];p=max(p,i);num++;}
}
//printf(" %d
",p);
ll mi = 0x7f7f7f7f7f7f7f7f;
for(int i = p+1; i <= n; i++){
if(a[i])mi=min(mi,a[i]);
}
if(mi==0x7f7f7f7f7f7f7f7f){
printf("Richman
");continue;
}
printf("%lld
",mi-1+ans);
}
return 0;
}
/*
2
7 6
4 1 0 3 0 0 1
6 5
4 5 0 3 0 0
*/