BZOJ[3728]PA2014 Final Zarowki

有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
HINT

解释:将2和10换成4和4。配对方案为1-1,4-4,4-4,5-5,7-7,11-12。

Sol:

/*
将手头上有的亮度a及要求的房间亮度b都降序排出来
一个个拿出要求的亮度,将大于等于它的a的值一个个丢到小根堆q里
然后看下q是否为空,如果为空说明此时要去商店拿一个亮度与当前一致的
如果q不为空,则弹出堆顶值,并将两者的差值加到一个大堆根q1中
全部做完后,如果还有名额去商店拿灯泡,则弹出q1的堆顶 
*/
#include
#include
#include
#define N 500050
using namespace std;
priority_queue<int,vector<int>,greater<int> >q;
priority_queue<int,vector<int>,less<int> >q1;
inline bool cmp(int a,int b)
{
    return a>b;
}
int a[N],b[N];
int n,k,t,x;
long long ans;
int main()
{
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;i++) 
        scanf("%d",a+i);
    for(int i=1;i<=n;i++) 
        scanf("%d",b+i);
    sort(a+1,a+n+1,cmp);//手头上的灯,降序排好 
    sort(b+1,b+n+1,cmp);//要求的灯的亮度 
    t=1;
    for(int i=1;i<=n;i++)
    {
        while(a[t]>=b[i]&&t) //将大于第i个所要求的灯亮度的灯丢到小根堆里 
             q.push(a[t++]);
        if(q.empty()) //如果堆为空 
        {
            ans=ans+b[i];//使用当前亮度 
            if(k) //如果还可以换灯泡 
                    k--;
            else //堆中没有大于当前要求亮度的,又没办法去商店拿,于是无解 
                   return printf("NIE"),0;
        }
        else //说明堆中还有元素值大于当前亮度的 
        {
           x=q.top();
           q.pop();
           ans=ans+x;//从小根堆中取出一个大于等于当前要求亮度的且值最小的,用上之 
           q1.push(x-b[i]);//差值放到大根堆中 
        }
     }
    while(k--&&!q1.empty())//如果还可以换灯泡的话 
    {
        ans=ans-q1.top();
    //    cout<<"change it ans is "<
        q1.pop();
    }
return printf("%lld",ans),0;
}

 

你可能感兴趣的:(BZOJ[3728]PA2014 Final Zarowki)