BSOJ 2423 -- 【PA2014】Final Zarowki

Description

有n个房间和n盏灯,你需要在每个房间里放入一盏灯。每盏灯都有一定功率,每间房间都需要不少于一定功率的灯泡才可以完全照亮。 
你可以去附近的商店换新灯泡,商店里所有正整数功率的灯泡都有售。但由于背包空间有限,你至多只能换k个灯泡。 
你需要找到一个合理的方案使得每个房间都被完全照亮,并在这个前提下使得总功率尽可能小。

Input

第一行两个整数n,k(1<=k<=n<=500000)。 
第二行n个整数pi,表示你现有的灯泡的功率。 
第三行n个整数wi,表示照亮每间房间所需要的最小功率。

Output

如果无法照亮每间房间,仅输出NIE。 
否则输出最小的总功率。

Sample Input

6 2 12 1 7 5 2 10 1 4 11 4 7 5 

Sample Output

33 

 

看到数据范围,想到可能是贪心。

我们先按照灯的功率从小到大排序,然后从小到大依次让灯去选择房间。很显然每个灯都要选择自己能够照明的需要功率最大的房间。然后剩下的没有选择的房间只能通过购买灯泡来完成。判断无解也非常容易,如果剩下的房间大于k个就无解。

但是如果剩下房间小于k个,我么显然可以将之前配对好的灯泡替换了来降低答案值。所以我们开个大根堆,维护配对了的p[i]-w[j]的最大值就可以了。

代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<set>
#include<map>
#include<vector>
#include<ctime>
#define ll long long
#define N 500005

using namespace std;
inline int Get() {int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}while('0'<=ch&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}return x*f;}

int n,k;
ll p[N],w[N];
priority_queue<ll>cha;
multiset<ll>s;
multiset<ll>::iterator it;
ll ans;
int main() {
	n=Get(),k=Get();
	for(int i=1;i<=n;i++) p[i]=Get();
	for(int i=1;i<=n;i++) {
		w[i]=Get();
		s.insert(w[i]);
	}
	sort(p+1,p+1+n);
	for(int i=1;i<=n;i++) {
		it=s.upper_bound(p[i]);
		if(it==s.begin()) continue ;
		it--;
		ans+=p[i];
		cha.push(p[i]-*it);
		s.erase(it);
		if(!s.size()) break;
	}
	
	if(s.size()>k) {cout<<"NIE";return 0;}
	for(it=s.begin();it!=s.end();it++) {
		ans+=*it;
	}
	k-=s.size();
	for(int i=1;i<=k;i++) {
		ans-=cha.top();
		cha.pop();
		if(!cha.size()) break;
	}
	cout<<ans;
	return 0;
}

 

posted @ 2018-09-28 07:24  hec0411  阅读(154)  评论(0编辑  收藏  举报