洛谷 CF1837F Editorial for Two

洛谷 CF1837F Editorial for Two

语言:C++14(GCC9)

题面翻译

给定一个长度为 $ n $ 的序列,从中找出一个长度为 $ k $ 的子序列(可以不连续),然后将这个子序列划分为前后两部分,使得前半部分元素和与后半部分元素和的 $ \max $ 最小。输出这个最小值。

题目描述

Berland Intercollegiate Contest has just finished. Monocarp and Polycarp, as the jury, are going to conduct an editorial. Unfortunately, the time is limited, since they have to finish before the closing ceremony.

There were $ n $ problems in the contest. The problems are numbered from $ 1 $ to $ n $ . The editorial for the $ i $ -th problem takes $ a_i $ minutes. Monocarp and Polycarp are going to conduct an editorial for exactly $ k $ of the problems.

The editorial goes as follows. They have a full problemset of $ n $ problems before them, in order. They remove $ n - k $ problems without changing the order of the remaining $ k $ problems. Then, Monocarp takes some prefix of these $ k $ problems (possibly, an empty one or all problems). Polycarp takes the remaining suffix of them. After that, they go to different rooms and conduct editorials for their problems in parallel. So, the editorial takes as much time as the longer of these two does.

Please, help Monocarp and Polycarp to choose the problems and the split in such a way that the editorial finishes as early as possible. Print the duration of the editorial.

输入格式

The first line contains a single integer $ t $ ( $ 1 \le t \le 10^4 $ ) — the number of testcases.

The first line of each testcase contains two integers $ n $ and $ k $ ( $ 1 \le k \le n \le 3 \cdot 10^5 $ ) — the number of problems in the full problemset and the number of problems Monocarp and Polycarp are going to conduct an editorial for.

The second line contains $ n $ integers $ a_1, a_2, \dots, a_n $ ( $ 1 \le a_i \le 10^9 $ ) — the time each editorial takes.

The sum of $ n $ over all testcases doesn’t exceed $ 3 \cdot 10^5 $ .

输出格式

For each testcase, print a single integer — the smallest amount of time the editorial takes, if Monocarp and Polycarp can choose which $ k $ of $ n $ problems to conduct an editorial for and how to split them among themselves.

样例 #1

样例输入 #1

6
5 4
1 10 1 1 1
5 3
1 20 5 15 3
5 3
1 20 3 15 5
10 6
10 8 20 14 3 8 6 4 16 11
10 5
9 9 2 13 15 19 4 9 13 12
1 1
1

样例输出 #1

2
6
5
21
18
1

一种简单的思路是枚举分割点,前后各扫一下,贪心的记录前 i i i 个元素在合法条件下的最多能拿多少个数字,再进行匹配,看是否有任意一组可行解大于 k k k 即可。具体实现看代码。
用堆实现其实很方便, s i z e ( ) size() size() 统计当前能拿多少数字, t o p ( ) top() top() 更新当前解等等。 然后本题的难点其实是在开 l o n g l o n g 。 然后本题的难点其实是在开 long long。 然后本题的难点其实是在开longlong

复杂度 O ( N l o g 2 N ) O(Nlog^2N) O(Nlog2N)

#include<bits/stdc++.h>
#define int long long
#define pq priority_queue
using namespace std;
const int maxn = 3e5 + 5;
int q, n, k;
int ans;
int a[maxn];
int l, r;

bool check(int mid) {
	pq<int> q;
	int need[maxn];
	int sum = 0;
	for(int i = 1;i <= n;++ i) {
		q.push(a[i]);
		sum += a[i];
		for(;(sum > mid);) sum -= q.top(),q.pop(); 
		need[i] = q.size();
	}sum = 0;
	while(!q.empty()) q.pop();
	for(int i = n;i > 0;i --) {
		q.push(a[i]);
		sum += a[i];
		for(; (sum > mid);) sum -= q.top(),q.pop();
		if(q.size() + need[i - 1] >= k)
			return 1;
	}
	return 0;
}

signed main() {
	cin >> q;
	while (q--) {
		l = 0;
		r = 0;
		cin >> n >> k;
		for(int i = 1;i <= n;i ++) {
			cin >> a[i];
			r += a[i];
		}
		while(l <= r) {
			int mid = (l + r) >> 1;
			if(check(mid)) {
				r = mid - 1;
				ans = mid;
			}
			else l = mid + 1;
		}
		cout << ans << '\n';
	}
	
	return 0;
}
  • 12
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值