emmmmm,cogsGG了,所以刷bzoj好了,正好学长给了个权限号
3728: PA2014Final Zarowki
这道题还是蛮容易看出来是贪心的。考虑如何尽量少换灯泡,很容易想到,先拍一遍序,然后对于每一个点,选择功率大于他的里面功率最小的那个灯泡,这样可以尽可能少的换灯泡。
但这样是不对的,因为如果我们从小到大枚举的话,小的可能把本来能用于大的房间的灯泡占用了,大的占了更大的,最终导致需要功率最高的房间需要换灯泡,这样的话总功率并不是
最优的,于是我们考虑从大往小枚举,于是我们可以维护一个堆,从大到小枚举,对于每一个房间,将所有大于他的灯泡压入堆中,取出一个最小的即可。如果没有比他更大的了,那么就对
k--,就是换一个灯泡,换到最后,如果k<0了,就意味着不可行,输出NIE,如果k还有剩余,我们就可以对之前那些虽然满足但不是最优的房间进行换灯泡(实际灯泡功率大于需要功率)
这里我们也可以用一个堆来维护,每次取出相差最大的换上即可。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include<bits/stdc++.h> 2 #define ll long long 3 using namespace std; 4 int n,k,p[500005],w[500005]; 5 ll ans; 6 priority_queue<int,vector<int>,greater<int> >S; 7 priority_queue<int>P; 8 int main() 9 { 10 scanf("%d%d",&n,&k); 11 for(int i=1;i<=n;i++)scanf("%d",&p[i]); 12 for(int i=1;i<=n;i++)scanf("%d",&w[i]); 13 sort(p+1,p+n+1);sort(w+1,w+n+1); 14 for(int i=n,j=n;i>=1;i--){ 15 while(p[j]>=w[i]&&j>=1){ 16 S.push(p[j]);j--; 17 } 18 if(!S.empty()){ 19 int u=S.top();S.pop(); 20 ans+=(ll)u;P.push(u-w[i]); 21 } 22 else { 23 k--;ans+=w[i]; 24 } 25 } 26 if(k<0){ 27 cout<<"NIE";return 0; 28 } 29 else { 30 while(k--&&!P.empty()){ 31 int u=P.top();P.pop(); 32 ans-=(ll)u; 33 }cout<<ans; 34 } 35 return 0; 36 }