9.27T2 贪心+堆

2.Final Zarowki 2423

(Zarowki)

【问题描述】

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

【输入】

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

【输出】

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

【样例输入】

6 2

12 1 7 5 2 10

1 4 11 4 7 5 
【样例输出】

33 
【样例说明】

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

 

 

题解:先对灯和房间进行从大到小的排序,然后对于每一个房间把前面选剩下大于它的灯泡全部扔进堆里面,然后找出最小值也就是最接近房间的了

如果堆是空的,那么后面堆里面一定会有剩下来的灯泡,剩下的灯泡就变成这个值,无关灯泡是哪一个,那么这个匹配的就是房间自己的值,同时使用一次机会

如果光是满足条件大于k,输出-1

反之剩下一些次数,把每个房间对应值的差值扔进大根堆里面维护,取出k-num个减掉就是答案了,可以证明这是最优的

贪心还是不行啊

code:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<queue>
 4 #include<algorithm>
 5 using namespace std;
 6 priority_queue<int>p;
 7 priority_queue<int,vector<int>,greater<int> >q;
 8 bool cmp(int a,int b){
 9     return a>b;
10 }
11 int s[500005],w[500005],check[500005],num;
12 int main(){
13     //freopen("Zarowki.in","r",stdin);
14     //freopen("Zarowki.out","w",stdout);
15     int n,k;scanf("%d%d",&n,&k);
16     for(int i=1;i<=n;i++)scanf("%d",&s[i]);
17     for(int i=1;i<=n;i++)scanf("%d",&w[i]);
18     int head=1;
19     sort(s+1,s+n+1,cmp);
20     sort(w+1,w+n+1,cmp);
21     long long ans=0;
22     for(int i=1;i<=n;i++){
23         while(s[head]>=w[i]&&head<=n){
24             q.push(s[head]);
25             head++;
26         }
27         if(!q.empty()){
28             int t=q.top();
29             q.pop();
30             check[i]=t;
31         }
32         else{
33             check[i]=w[i];
34             num++;
35         }
36         ans+=check[i];
37     }
38     if(num>k){
39         cout<<"NIE";
40         return 0;
41     }
42     for(int i=1;i<=n;i++)
43         p.push(check[i]-w[i]);
44     for(int i=1;i<=k-num;i++){
45         ans-=p.top();
46         p.pop();
47     }
48     cout<<ans;
49     return 0;
50 }

over

posted @ 2018-09-27 15:54  saionjisekai  阅读(63)  评论(0编辑  收藏  举报