首页 > 其他分享 >wqs 二分简记

wqs 二分简记

时间:2023-01-30 21:11:19浏览次数:53  
标签:二分 int ll wqs 切点 简记 check

wqs 二分一般用于解决这样的问题:\(n\) 个物品,恰好选 \(x\) 个获得的最大或最小价值为 \(F(x)\),求 \(F(K)\)。\(F\) 需要具有凸性质。

二分一个斜率 \(k\),check 时,用斜率为 \(k\) 的直线去切凸包。具体地,将每个物品的价值减去 \(k\),取消个数限制,求出最大或最小的价值 \(b\) 和此时选择的物品个数 \(x\),则可以发现 \(b=F(x)-kx\),故切点为 \((x,kx+b)\)。如果它不是切点,其对应的截距必然更劣。可以画图理解。如果有多个切点,可以想办法保证取到最左或者最右的切点。

例题:Luogu P4694 [PA2013] Raper

基本上是 wqs 二分的模板题。首先我们可以将题目转化为:一张左右各 \(n\) 个点的二分图,左部第 \(i\) 个点向右部 \(j\ge i\) 的点连边,一个匹配的权值为两点的点权和,求恰好 \(K\) 对匹配的最小权值和。这显然是一个费用流模型,我们知道费用流问题肯定是凸的(现在我还不会证明),所以这个函数应当是下凸的。

于是跑 wqs 二分,check 是一个很容易的反悔贪心,注意实现细节保证取的匹配数最少或最多。

#include<bits/stdc++.h>
using namespace std;
constexpr int N=5e5+5;
typedef long long ll;
typedef pair<ll,int>pli;
int n;ll a[N],b[N];
pli check(ll k){
	ll sum=0;int cnt=0;
	priority_queue<pli,vector<pli>,greater<pli>>q;
	for(int i=n;i>=1;i--){
		q.emplace(b[i]-k,i);
		if(q.top().first+a[i]<0){
			auto[val,pos]=q.top();q.pop();
			sum+=a[i]+val;cnt+=!!pos;
			q.emplace(-a[i],0);
		}
	}
	return pair(sum,cnt);
}
int main(){
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	int K;cin>>n>>K;
	for(int i=1;i<=n;i++)cin>>a[i];
	for(int i=1;i<=n;i++)cin>>b[i];
	ll l=0,r=2e9,ans=1;while(l<=r){
		ll mid=(l+r)>>1;
		auto[b,cnt]=check(mid);
		if(cnt<=K)ans=b+mid*K,l=mid+1;
		else r=mid-1;
	}
	cout<<ans<<'\n';
	return 0;
}

标签:二分,int,ll,wqs,切点,简记,check
From: https://www.cnblogs.com/hihihi198/p/17077247.html

相关文章

  • 二分
    二分思路二分模板整数二分boolcheck(intx){/*...*/}//检查x是否满足某种性质//区间[l,r]被划分成[l,mid]和[mid+1,r]时使用:intbsearch_1(intl,int......
  • 二分查询
    话不多说直接上代码(Coding):/***二分查找*二分查找是一种算法在一个有序的元素列表中查询一个元素如果存在则返回该元素的索引没有则返回null*比一般查询......
  • LeetCode | 704. 二分查找
    ​题:力扣704.二分查找给定一个 n 个元素有序的(升序)整型数组 nums和一个目标值 target ,写一个函数搜索 nums 中的target,如果目标值存在返回下标,否则返回-1......
  • 二分查找
    二分查找的列表必须是有序列表。从列表中间开始查找,如果给定的值和中间值相等则查找成功;如果给定的值大于或者小于中间的值,则从表中大于或者小于中间值的那一半中查找,......
  • 二分图
    约定如无特别说明,本文中的\(n,m\)分别为左右部点数,且总有\(n\leqslantm\)。边集记为\(E\),边数记为\(e\)。定义二分图是如下的一张图:可以将\(V\)划分为\(......
  • 求三次方根二分查找
    直接写#include<iostream>#include<cmath>#include<iomanip>usingnamespacestd;doublen;intmain(){boolsign;cin>>n;doublel=-10000,r=100......
  • 二分查找的三种形式&两道力扣
    前言过年前刷Leetcode的时候遇到这样一道题目:354.俄罗斯套娃信封问题-力扣(Leetcode)其中使用patiencesorting这个算法的做法中,因为牌堆顶是有序数组,所以可以使用二分......
  • 代码随想录 | Day 1 | LC 27 移除元素、704 二分查找
    704.二分查找题目解法1:纯遍历classSolution{publicintsearch(int[]nums,inttarget){for(inti=0;i<nums.length;i++){i......
  • 704.二分查找
    题目:给定一个n个元素有序的(升序)整型数组nums和一个目标值target,写一个函数搜索nums中的target,如果目标值存在返回下标,否则返回-1。*要求输入:nums=[-1,0,......
  • 基于matlab的二分法求解方程的根(Bisection method)
    ​​https://zhuanlan.zhihu.com/p/139961663​​​​http://www.zhihuishi.com/source/15627.html​​......