F. Editorial for Two(二分答案+反悔贪心)

这篇具有很好参考价值的文章主要介绍了F. Editorial for Two(二分答案+反悔贪心)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

F. Editorial for Two(二分答案+反悔贪心)

F. Editorial for Two

1、问题

给定一个 n n n k k k,以及一个长度为 n n n数组。现在从 n n n个数中,挑出 k k k个数,称作个子序列。然后将这个子序列分成两部分,记作子序列1和子序列2。那么子序列1和子序列2都有一个对应的和。这两个和能够比较出一个最大值。现在我们要求的是最大值的最小值

2、分析

这里有一个很常用的套路,当题目中让我们求最大值的最小值或者最小值的最大值的时候,一般采用二分来解决。

我们这里二分最终的答案。

对于二分而言,难点在于 c h e c k check check函数的书写。

这道题中, c h e c k check check函数的作用是判断二分过程中的 m i d mid mid值是否合理。

F. Editorial for Two(二分答案+反悔贪心)
那么这个挑出最多 k 1 k1 k1个数的过程,用到了反悔贪心,反悔贪心的思路就是当所选数字的和小于 m i d mid mid的时候,就尽可能多的选数字,当大于 m i d mid mid的时候,就删除选择数字中的最大值,目的是留出更大空间选择更多的数字,而这个选择最大值的过程可以用大根堆来优化。

除此以外,图中前缀后缀划分的位置是不确定的,所以我们需要枚举所有的划分位置,找到一个可行的方案。

因此,我们可以先利用反悔贪心先预处理出来所有的前缀后缀中最多选择的数字 k 1 , k 2 k1,k2 k1,k2。然后再枚举划分位置,判断是否存在一组 k 1 + k 2 ≥ k k1+k2 \geq k k1+k2k文章来源地址https://www.toymoban.com/news/detail-473920.html

3、代码

#include<bits/stdc++.h>
#define endl '\n'
#define int long long
using namespace std;


bool check(int maxv, int n, vector<int>a, int k)
{
	vector<int>f(n + 1, 0), g(n + 1, 0);
	priority_queue<int>q, qq;
	int sum = 0;
	for(int i = 0; i < n; i ++)
	{
		if(sum + a[i] <= maxv)
		{
			sum += a[i];
			q.push(a[i]);
			f[i + 1] = f[i] + 1;
		}
		else
		{
			q.push(a[i]);
			sum += a[i];
			sum -= q.top();
			q.pop();
			f[i + 1] = f[i];
		}
	}
	sum = 0;
	reverse(a.begin(), a.end());
	for(int i = 0; i < n; i ++)
	{
		if(sum + a[i] <= maxv)
		{
			sum += a[i];
			qq.push(a[i]);
			g[i + 1] = g[i] + 1;
		}
		else
		{
			sum += a[i];
			qq.push(a[i]);
			sum -= qq.top();
			qq.pop();
			g[i + 1] = g[i]; 
		}
	}

	for(int i = 1; i <= n; i ++ )
	{
		if(f[i] + g[n - i] >= k)
			return true;			
	}
	return false;

}

void solve()
{
	int n, k;
	cin >> n >> k;
	vector<int>a(n);
	int sum = 0;
	for(int i = 0; i < n; i ++)
	{
		cin >> a[i];
		sum += a[i];
	}
	int l = 0, r = sum;
	while(l < r)
	{
		int mid = l + r >> 1;
		if(check(mid, n, a, k))
			r = mid;
		else
			l = mid + 1;
	}
	cout << l << endl;
}

signed main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	int t;
	cin >> t;
	while(t--)
	solve();
}

到了这里,关于F. Editorial for Two(二分答案+反悔贪心)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 扫地机器人(二分算法+贪心算法)

    1.  if(robot[i]-len=sweep)这个代码的意思是——如果机器人向左移动len个长度后,比现在sweep的位置(现在已经覆盖的范围)还要靠左,就是覆盖连续不起来,呢么这个len就是有问题的,退出函数,再继续循环。 2.  显然当每个机器人清扫的范围相同时,所用时间最小,所以这时

    2024年01月20日
    浏览(33)
  • Peter算法小课堂—贪心与二分

    题目描述: 有n辆车大甩卖,第i辆车售价a[i]元。有m个人带着现金来申请购买,第i个到现场的人带的现金为b[i]元,只能买价格不超过其现金额的车子。你是大卖场总经理,希望将车和买家尽量多地进行一对一配对,请问最多卖出多少辆车? 贪心法模板: 比如说:每次挑最便

    2024年02月02日
    浏览(28)
  • C++二分算法(二分查找&二分答案)细节详解

     二分算法可以分为 二分查找 和 二分答案 。 以在一个 升序数组 中查找一个数为例。它每次考察数组当前部分的 中间元素 ,如果中间元素刚好是要找的,就结束搜索过程;如果中间元素小于所查找的值,那么左侧的只会更小,不会有所查找的元素,只需到右侧查找;如果

    2024年02月08日
    浏览(39)
  • 力扣hot100 最长递增子序列 线性DP 贪心 二分

    Problem: 300. 最长递增子序列 时间复杂度: O ( n 2 ) O(n^2) O ( n 2 ) 空间复杂度: O ( n ) O(n) O ( n ) 👨‍🏫 参考题解 时间复杂度: O ( n log ⁡ n ) O(nlog{n}) O ( n lo g n ) 空间复杂度: O ( n ) O(n) O ( n )

    2024年01月20日
    浏览(29)
  • 算法每日一题: 分割数组的最大值 | 动归 | 分割数组 | 贪心+二分

    Hello,大家好,我是星恒 呜呜呜,今天给大家带来的又是一道经典的动归难题。 题目:leetcode 410 给定一个非负整数数组 nums 和一个整数 k ,你需要将这个数组分成 k_ 个非空的连续子数组。 设计一个算法使得这 k _个子数组各自和的最大值最小。 示例: 示例 1: 示例 2: 示例

    2024年01月22日
    浏览(34)
  • Python数据结构与算法篇(五)-- 二分查找与二分答案

    1.1 定义         二分查找又称折半查找、二分搜索、折半搜索等,是一种在静态查找表中查找特定元素的算法。         所谓静态查找表,即只能对表内的元素做查找和读取操作,不允许插入或删除元素。         使用二分查找算法,必须保证查找表中存放的是有

    2023年04月20日
    浏览(37)
  • 【二分答案】CF1661 C

    Problem - C - Codeforces 题意: 思路: 在check的时候,我们要尽量用算贡献的思想,并且大胆贪心 Code:

    2024年02月15日
    浏览(30)
  • 【每日一题Day331】LC2560打家劫舍 IV | 二分查找 + 贪心

    打家劫舍 IV【LC2560】 沿街有一排连续的房屋。每间房屋内都藏有一定的现金。现在有一位小偷计划从这些房屋中窃取现金。 由于相邻的房屋装有相互连通的防盗系统,所以小偷 不会窃取相邻的房屋 。 小偷的 窃取能力 定义为他在窃取过程中能从单间房屋中窃取的 最大金额

    2024年02月07日
    浏览(31)
  • 【算法】【Python3、动态规划、贪心、二分查找】力扣1671. 得到山形数组的最少删除次数

    1671. 得到山形数组的最少删除次数 给定一个整数数组 nums ,我们定义该数组为山形数组当且仅当: nums 的长度至少为 3。 存在一个下标 i 满足 0 i len(nums) - 1 且: nums[0] nums[1] ... nums[i - 1] nums[i] nums[i] nums[i + 1] ... nums[len(nums) - 1] 现在,给定整数数组 nums ,我们的目标是将其变为

    2024年01月18日
    浏览(44)
  • LeetCode2560. House Robber IV——二分答案+动态规划

    There are several consecutive houses along a street, each of which has some money inside. There is also a robber, who wants to steal money from the homes, but he refuses to steal from adjacent homes. The capability of the robber is the maximum amount of money he steals from one house of all the houses he robbed. You are given an integer array nums representi

    2024年02月21日
    浏览(26)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包