【题解】 闷声刷大题 带悔贪心+wqs二分

Legend

大神犇 YCY 现在有 (k) 道神题要刷(假定神题没有区别),刷一道题要分两个步骤,必须要先想出正解再写出正解。

他一共有 (n) 天时间可以刷题,但他每天最多只能想出一道题和写出一道题,可以在同一天想出和写出同一道题。

定义刷一道题的代价为想的代价 (a_i) + 写的代价$ b_i$,YCY 想最小化 (k) 道题的代价和。

(n le 150\,000),代价都是正数。

Editorial

首先这个题有个很显然的费用流搞法,显然就 TLE 了。

其次有个 (O(n^3)) 的 dp,设 (dp_{i,j,k}) 表示考虑第 (i) 想题和第 (j) 天做题匹配,已经做完了 (k) 道题的最小代价。

转移则按是否 (i,j) 配对来转移,不配对则 (i gets i+1)(j gets j+1),否则两个同时 (+1)

这个 dp 可以被优化到 (O(n^2log (a+b))),第三维可以通过 (wqs) 二分搞掉。

为什么是凸的?

你可以看成一个二分图的带权匹配,这显然是个下凸函数。考虑它如果不下凸,则我们可以通过构造更优解来进行反证。

现在复杂度的瓶颈在于 (O(n^2)) 的 dp,它实在是太慢了,有没有什么其它搞法?

答案是有的,就是带悔贪心。

考虑维护一个待选题目集合 (S),我们从左到右加入“想题目”,同时每天考虑是否“做题目”。

如果做题目 + 想题目的代价 (le 0),我们就考虑形成这个配对,否则不形成。

但是之后出现了更优的“做题目”,怎么办?我们要把当前的“想”配对的“做”撤回,即往 (S) 中加入负的“做”的代价。

复杂度 (O(nlog n log (a+b)))

Code

特别地,根据二分的实现方法,你需要为“想”和撤回“做”两种不同的贪心方式定义先后顺序,

因为先后顺序的不同会导致 wqs 二分到的位置不一。

#include <bits/stdc++.h>

#define debug(...) fprintf(stderr ,__VA_ARGS__)
#define __FILE(x)
	freopen(#x".in" ,"r" ,stdin);
	freopen(#x".out" ,"w" ,stdout)
#define LL long long

const int MX = 150000 + 23;

using namespace std;

int read(){
	char k = getchar(); int x = 0;
	while(k < '0' || k > '9') k = getchar();
	while(k >= '0' && k <= '9') x = x * 10 + k - '0' ,k = getchar();
	return x;
}

int n ,k;
int a[MX] ,b[MX];
LL ans;

struct GOOD{
	int type;
	LL x;
	bool operator <(const GOOD& B)const{
		return x == B.x ? type > B.type : x > B.x;
	}
};

int check(LL mid){
	int choose = 0;
	ans = 0;
	priority_queue<GOOD> q;
	for(int i = 1 ; i <= n ; ++i){
		q.push((GOOD){1 ,a[i] - mid});
		if(!q.empty() && q.top().x + b[i] <= 0){
			if(q.top().type == 1) ++choose;
			ans += b[i] + q.top().x;
			q.pop();
			q.push((GOOD){2 ,-b[i]});
		}
	}
	return choose;
}

int main(){
	n = read() ,k = read();
	for(int i = 1 ; i <= n ; ++i) a[i] = read();
	for(int i = 1 ; i <= n ; ++i) b[i] = read();
	LL l = 0 ,r = 2e9 ,mid;
	while(l <= r){
		// debug("%d %d
" ,l ,r);
		int mid = (l + r) / 2;
		if(check(mid) >= k) r = mid - 1;
		else l = mid + 1;	
	}
	check(r + 1);
	printf("%lld
" ,ans + (r + 1LL) * k);
	return 0;
}
原文地址:https://www.cnblogs.com/imakf/p/14428415.html