【BZOJ3728】PA2014Final Zarowki
Description
有n个房间和n盏灯,你需要在每个房间里放入一盏灯。每盏灯都有一定功率,每间房间都需要不少于一定功率的灯泡才可以完全照亮。
你可以去附近的商店换新灯泡,商店里所有正整数功率的灯泡都有售。但由于背包空间有限,你至多只能换k个灯泡。
你需要找到一个合理的方案使得每个房间都被完全照亮,并在这个前提下使得总功率尽可能小。
Input
第一行两个整数n,k(1<=k<=n<=500000)。
第二行n个整数p[i](1<=p[i]<=10^9),表示你现有的灯泡的功率。
第三行n个整数w[i](1<=w[i]<=10^9),表示照亮每间房间所需要的最小功率。
Output
如果无法照亮每间房间,仅输出NIE。
否则输出最小的总功率。
Sample Input
6 2
12 1 7 5 2 10
1 4 11 4 7 5
12 1 7 5 2 10
1 4 11 4 7 5
Sample Output
33
HINT
解释:将2和10换成4和4。配对方案为1-1,4-4,4-4,5-5,7-7,11-12。
题解:先贪心,将灯泡和房间从大到小排序,如果有多个灯泡能够照亮当前的房间,则选择功率最小的,用堆维护即可。如果没有灯泡能照亮当前房间,则买一个。
但是这样贪心有可能出错,所以我们在最后判断:如果还能买灯泡,则选取(当前功率-需要功率)最大的几个换掉即可。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
const int maxn=500010;
int n,m;
typedef long long ll;
ll ans;
ll p[maxn],w[maxn],c[maxn];
priority_queue<ll> q;
bool cmp(ll a,ll b)
{
return a>b;
}
int rd()
{
int ret=0,f=1; char gc=getchar();
while(gc<'0'||gc>'9') {if(gc=='-')f=-f; gc=getchar();}
while(gc>='0'&&gc<='9') ret=ret*10+gc-'0',gc=getchar();
return ret*f;
}
int main()
{
n=rd(),m=rd();
int i,j;
for(i=1;i<=n;i++) p[i]=rd();
for(i=1;i<=n;i++) w[i]=rd(),ans+=w[i];
sort(p+1,p+n+1,cmp),sort(w+1,w+n+1,cmp);
for(i=j=1;i<=n;i++)
{
for(;j<=n&&p[j]>=w[i];j++) q.push(-p[j]);
if(q.empty())
{
if(!m)
{
printf("NIE");
return 0;
}
m--,c[i]=0;
}
else c[i]=-q.top()-w[i],q.pop();
}
if(m)
{
sort(c+1,c+n+1,cmp);
for(i=1;i<=m;i++) c[i]=0;
}
for(i=1;i<=n;i++) ans+=c[i];
printf("%lld",ans);
return 0;
}