牛客小白月赛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 求至多操作 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
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
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, less>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;
}

你可能感兴趣的:(小白月赛,算法,c++)