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