【BZOJ3728】【PA2014】—Final Zarowki(思维题)

传送门

考虑对于每一个房间,肯定是选择差最小的那个灯泡
而如果满足的灯泡不够了就需要换一个过来
最后如果还有剩下可以换的肯定是要把差最大的给换掉

那就有个大致的做法了

将房间和灯泡从大到小排序
维护一个堆表示比当前房间大的剩下还可以用的灯泡
如果还有剩的就选一个最小的,并将他们的差再放入一个堆里面
没有的话就花一次机会换一个灯泡过来

最后如果有剩下的机会再换差最大的几对

#include<bits/stdc++.h>
using namespace std;
const int RLEN=1<<20|1;
#define ll long long
inline char gc(){return getchar();
	static char ibuf[RLEN],*ib,*ob;
	(ib==ob)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
	return (ib==ob)?EOF:*ib++;
}
inline int read(){
	char ch=gc();
	int res=0,f=1;
	while(!isdigit(ch))f^=(ch=='-'),ch=gc();
	while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
	return f?res:-res;
}
const int N=500005;
priority_queue<int,vector<int>,greater<int> >f1;
priority_queue<int>f2;
int n,k,a[N],b[N];
ll ans;
int main(){
	n=read(),k=read();
	generate(a+1,a+n+1,read);
	generate(b+1,b+n+1,read);
	sort(a+1,a+n+1);
	sort(b+1,b+n+1);
	for(int i=n,j=n;j;j--){
		for(;i&&b[j]<=a[i];i--){
			f1.push(a[i]);
		}
		if(!f1.size()){
			k--,ans+=b[j];
			if(k==-1){
				puts("NIE");return 0;
			}
		}
		else{
			int x=f1.top();f1.pop();
			ans+=x,f2.push(x-b[j]);
		}
	}
	while(k--)ans-=f2.top(),f2.pop();
	cout<<ans;
}
posted @ 2019-04-03 20:27  Stargazer_cykoi  阅读(149)  评论(0编辑  收藏  举报