饿饿 饭饭
题目描述:
n个同学,每个人需要打
a[i]
份饭,排队打饭,每个在队头的人才能打饭,且打完一份饭就会到队尾去,打够a[i]
份饭后就离开了,现在食堂一共只有K
份饭,问最后的队伍序列长什么样,你只需要输出剩下的没走的人在原序列的id,按当前结束的队伍排列进行输出
思路:
二分答案
显然我们可以二分出需要进行多少轮打饭能打完
K
份饭
check
也很好写,求一个,跟 K
进行判断就行如果无论如何都无法打完
K
份饭,则是-1否则,我们可以先通过打
K-1
份饭得到进行最后一轮打饭之前的人的情况,用一个队列存下来,然后模拟一遍最后一轮的过程就行
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
#define inf 0x3f3f3f3f
#define mod7 1000000007
#define mod9 998244353
#define m_p(a,b) make_pair(a, b)
#define mem(a,b) memset((a),(b),sizeof(a))
#define io ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
typedef long long ll;
typedef pair <int,int> pii;
#define MAX 300000 + 50
int n, m, k, x;
int tr[MAX];
bool judge(int mid){
int num = 0;
for(int i = 1; i <= n; ++i){
num += min(mid, tr[i]);
}
return num >= k;
}
void work(){
cin >> n >> k;
for(int i = 1; i <= n; ++i)cin >> tr[i];
int l = 0, r = k;
while(l <= r){
int mid = (l + r) / 2;
if(judge(mid))r = mid - 1;
else l = mid + 1;
}
if(l == k + 1)cout << -1 << endl;
else{
vector<int>a;
ll sum = 0;
queue<pii>q;
for(int i = 1; i <= n; ++i){
k -= min(tr[i], l - 1);
tr[i] = max(0ll, tr[i] - l + 1);
if(tr[i])q.push(m_p(i, tr[i]));
}
k -= sum;
while(k--){
auto x = q.front();q.pop();
--x.second;
if(x.second)q.push(x);
}
while(!q.empty()){
cout << q.front().first << ' ';
q.pop();
}
cout << endl;
}
}
signed main(){
io;
work();
return 0;
}