牛客小白月赛77,小Why的简单加减,2023/9/1
链接:登录—专业IT笔试面试备考平台_牛客网
来源:牛客网
时间限制:C/C++ 2秒,其他语言4秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
给定长度为n 的序列a,你可以执行以下操作至多 k 次:
∙ 选择 l,r (1≤l<r≤n)l,r ,令 al=al−1,ar=ar+1。
求至多操作 k次后序列 a中最多的非负整数个数。
输入描述:
第一行包含两个整数 n,k (2≤n≤106,0≤k≤1012)n,k \ (2 \leq n \leq 10^6 ,0 \leq k \leq 10^{12})n,k (2≤n≤106,0≤k≤1012) ,表示序列 aaa 的长度和操作次数。 第二行包含 nnn 个整数 a1 ... an (−106≤ai≤106)a_1 \ ... \ a_n \ (-10^6 \leq a_i \leq 10^6)a1 ... an (−106≤ai≤106),表示序列 aaa。
输出描述:
输出一个整数,表示至多的非负整数个数。
示例1
输入
3 2 0 -1 -1
输出
2
示例2
输入
4 3 3 0 -1 -2
输出
4
解析:思维,模拟
此题有多种情况:
我们假定数组为arr,数组arr的前缀和为sum,数组中
非负数的个数为num。
再定义一个优先队列q:从大到小保存前面遇到的已经被填满
的负数;
当arr[i]<0且arr[i]的前i-1个数的前缀和sum>=-arr[i]
k>=-arr[i]时:arr[i]能用前面的数填满且前面的非负数的
个数不变
当第一种情况的两个条件有一个不满足时:
若前面被填满的负数中绝对值比当前的arr[i]大的,这说明
优先填满当前的arr[i]会更优
同时将sum设置为无限大
将sum设置为无限大:
因为以后可以一直将q.top()中出来的那个数当作al;
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<utility>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
using namespace std;
typedef long long LL;
const int N = 1e6 + 5;
LL n, k;
LL arr[N], sum;
int main() {
cin >> n >> k;
for (int i = 1; i <= n; i++) {
scanf("%lld", &arr[i]);
}
int num = 0;
priority_queue<LL, vector<LL>, less<LL>>q;
for (int i = 1; i <= n; i++) {
if (arr[i] >= 0) {
sum += arr[i];
num++;
}
else {
if (sum >= -arr[i] && k >= -arr[i]) {
sum += arr[i];
k += arr[i];
q.push(-arr[i]);
num++;
}
else {
if (!q.empty() && q.top() >= -arr[i]) {
k += q.top() + arr[i];
q.pop();
q.push(-arr[i]);
}
sum = 1e18;
}
}
}
cout << num << endl;
return 0;
}