洛谷P5470/LOJ3158[NOI2019]序列(贪心)
对于不用配对的$k-l$个元素,很明显选最大的是最优的。
然后重复$l$次凑对:如果当前还有不用配对的可以选(某一次凑了两个,或者一开始就有对出现),那么选没选的里面的最大值;否则要么选一个没选的和已选的凑对,再在另一个序列里再选一个,要么选都每选过的一对,这个可以用堆来做。
#include<cstdio> #include<cstring> #include<algorithm> #include<queue> using namespace std; typedef long long ll; const int N=200050; char rB[1<<21],*S,*T,wB[1<<21]; int wp=-1; inline char gc(){return S==T&&(T=(S=rB)+fread(rB,1,1<<21,stdin),S==T)?EOF:*S++;} inline void flush(){fwrite(wB,1,wp+1,stdout);wp=-1;} inline void pc(char c){if(wp+1==(1<<21))flush();wB[++wp]=c;} inline int rd(){ char c=gc(); while(c<48||c>57)c=gc(); int x=c&15; for(c=gc();c>=48&&c<=57;c=gc())x=(x<<3)+(x<<1)+(c&15); return x; } short buf[25]; inline void wt(ll x){ short l=-1; while(x>9){ buf[++l]=x%10; x/=10; } pc(x|48); while(l>=0)pc(buf[l--]|48); pc('\n'); } int a[N],b[N],ra[N],rb[N]; bool usea[N],useb[N]; inline bool cmpa(int x,int y){return a[x]>a[y];} inline bool cmpb(int x,int y){return b[x]>b[y];} struct dta{ int p; dta(int p):p(p){} inline bool operator <(const dta &x)const{return a[p]<a[x.p];} }; struct dtb{ int p; dtb(int p):p(p){} inline bool operator <(const dtb &x)const{return b[p]<b[x.p];} }; struct dte{ int p; dte(int p):p(p){} inline bool operator <(const dte &x)const{return a[p]+b[p]<a[x.p]+b[x.p];} }; priority_queue<dta> Qb,qa; priority_queue<dtb> Qa,qb; priority_queue<dte> Qe; int main(){ int T=rd(),n,k,l,i,tot,x,y,p,q,t,maxn; ll ans; while(T--){ n=rd();k=rd();l=rd(); for(i=1;i<=n;++i){a[i]=rd();ra[i]=rb[i]=i;} for(i=1;i<=n;++i)b[i]=rd(); memset(usea,0,sizeof(usea));memset(useb,0,sizeof(useb)); sort(ra+1,ra+n+1,cmpa);sort(rb+1,rb+n+1,cmpb); for(i=1,ans=tot=0;i<=k-l;++i){ usea[ra[i]]=useb[rb[i]]=1; ans+=a[ra[i]]+b[rb[i]]; } while(!Qa.empty())Qa.pop(); while(!qa.empty())qa.pop(); while(!Qb.empty())Qb.pop(); while(!qb.empty())qb.pop(); while(!Qe.empty())Qe.pop(); for(i=1;i<=n;++i)if(usea[i])if(useb[i])++tot; else{Qa.push(dtb(i));qb.push(dtb(i));} else if(useb[i]){Qb.push(dta(i));qa.push(dta(i));} else{ Qe.push(dte(i)); qa.push(dta(i));qb.push(dtb(i)); } while(l--){ while(!Qa.empty()&&useb[Qa.top().p])Qa.pop(); while(!Qb.empty()&&usea[Qb.top().p])Qb.pop(); while(!Qe.empty()&&(usea[Qe.top().p]||useb[Qe.top().p]))Qe.pop(); while(usea[qa.top().p])qa.pop(); while(useb[qb.top().p])qb.pop(); if(tot){ --tot; x=qa.top().p;y=qb.top().p;qa.pop();qb.pop(); ans+=a[x]+b[y]; usea[x]=useb[y]=1; if(x==y)++tot; else{ if(useb[x])++tot; else Qa.push(dtb(x)); if(usea[y])++tot; else Qb.push(dta(y)); } continue; } if(!Qa.empty()){y=Qa.top().p;x=qa.top().p;} else x=y=0; if(!Qb.empty()){p=Qb.top().p;q=qb.top().p;} else p=q=0; t=Qe.empty()?0:Qe.top().p; ans+=(maxn=max(a[t]+b[t],max(a[x]+b[y],a[p]+b[q]))); if(maxn==a[x]+b[y]){ Qa.pop();qa.pop(); usea[x]=useb[y]=1; if(useb[x])++tot; else Qa.push(dtb(x)); }else if(maxn==a[p]+b[q]){ Qb.pop();qb.pop(); usea[p]=useb[q]=1; if(usea[q])++tot; else Qb.push(dta(q)); }else{ Qe.pop(); usea[t]=useb[t]=1; } } wt(ans); } flush(); return 0; }