#对顶堆#nssl 1477 赛


分析

首先按小到大排序,考虑枚举两个都喜欢的个数\(i\)
那么只喜欢一个的个数各需要\(k-i\),剩下要补充到\(m-k*2+i\)个,
考虑用对顶堆维护大根堆大小仅有\(m-k*2+i\)即可


代码

#include <cstdio>
#include <cctype>
#include <algorithm>
#define rr register
using namespace std;
const int N=200011; typedef long long lll; lll ans=1e18,sum;
int n1,n2,n3,like[N],A[N],B[N],C[N],n,m,k,o[N];
inline signed iut(){
	rr int ans=0; rr char c=getchar();
	while (!isdigit(c)) c=getchar();
	while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
	return ans;
}
inline lll min(lll a,lll b){return a<b?a:b;}
inline void Swap(int &a,int &b){rr int t=a; a=b; b=t;}
struct Max_Heap{
	int cnt,heap[N];
	inline void Push(int now){
		heap[++cnt]=now;
		rr int x=cnt;
		while (x>1){
			if (heap[x]>heap[x>>1])
			    Swap(heap[x>>1],heap[x]),x>>=1;
			else return;
		}
	}
	inline void Pop(){
		heap[1]=heap[cnt--];
		rr int x=1;
		while ((x<<1)<=cnt){
			rr int y=x<<1;
			if (y<cnt&&heap[y+1]>heap[y]) ++y;
			if (heap[y]>heap[x]) Swap(heap[y],heap[x]),x=y;
			    else return;
		}
	}
}heap1;
struct Min_Heap{
	int cnt,heap[N];
	inline void Push(int now){
		heap[++cnt]=now;
		rr int x=cnt;
		while (x>1){
			if (heap[x]<heap[x>>1])
			    Swap(heap[x>>1],heap[x]),x>>=1;
			else return;
		}
	}
	inline void Pop(){
		heap[1]=heap[cnt--];
		rr int x=1;
		while ((x<<1)<=cnt){
			rr int y=x<<1;
			if (y<cnt&&heap[y+1]<heap[y]) ++y;
			if (heap[y]<heap[x]) Swap(heap[y],heap[x]),x=y;
			    else return;
		}
	}
}heap2;
signed main(){
	n=iut(); m=iut(); k=iut();
	for (rr int i=1;i<=n;++i) o[i]=iut();
	for (rr int T=iut();T;--T) like[iut()]=1;
	for (rr int T=iut();T;--T) like[iut()]|=2;
	for (rr int i=1;i<=n;++i){
		switch (like[i]){
			case 0:heap2.Push(o[i]); break;
			case 1:A[++n1]=o[i]; break;
			case 2:B[++n2]=o[i]; break;
			case 3:C[++n3]=o[i]; break;
		}
	}
	sort(A+1,A+1+n1),sort(B+1,B+1+n2),sort(C+1,C+1+n3);
	if (k<n3) for (rr int i=k+1;i<=n3;++i) heap2.Push(C[i]);
	for (rr int i=1;i<=n1;++i) sum+=A[i];
	for (rr int i=1;i<=n2;++i) sum+=B[i];
	rr int j1=n1,j2=n2,len=m-n1-n2;
	for (rr int i=0,t=min(n3,k);i<=t;++i,--len){
		for (;j1>k-i;--j1,++len) heap2.Push(A[j1]),sum-=A[j1];
		for (;j2>k-i;--j2,++len) heap2.Push(B[j2]),sum-=B[j2];
		if (j1+i>=k&&j2+i>=k){
			for (;len>0&&heap2.cnt;heap2.Pop(),--len)
			    sum+=heap2.heap[1],heap1.Push(heap2.heap[1]);
			if (heap1.cnt&&heap2.cnt)
			while (heap1.heap[1]>heap2.heap[1]){
				rr int X=heap1.heap[1],Y=heap2.heap[1];
				heap1.Pop(),heap2.Pop(),sum+=Y-X;
				heap1.Push(Y),heap2.Push(X);
			}
			if (!len) ans=min(ans,sum);
		}
		sum+=C[i+1];
	}
	if (ans==1e18) printf("-1");
	    else printf("%lld",ans);
	return 0;
}
posted @ 2020-08-14 21:16  lemondinosaur  阅读(109)  评论(0编辑  收藏  举报