#對頂堆#nssl 1477 賽
阿新 • • 發佈:2020-08-14
分析
首先按小到大排序,考慮列舉兩個都喜歡的個數\(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; }