原题:3N Numbers
原题大意
给3n个数,要求去掉n个数,使得剩下的2n个数里,前n个数减后n个数的值最大,求最大值。
算法分析
将球分为三种颜色,被取走的标为黑色,剩下的前n个为红色,后n个为蓝色,所以观察后发现,红色一定只出现在前面,蓝色一定只出现在后面,红色的最后一个位置是n~2n,蓝色的第一个位置一定是n+1~2n+1。设k为分界线,红球从前k个里面取,蓝球从后3*n-k里面取,k的取值为(n<=k<=2n),枚举k的取值,用优先队列维护最优值。
程序代码
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<stdlib.h>
#include<iostream>
#include<queue>
using namespace std;
priority_queue<int>QD;//大根堆
priority_queue<int,vector<int>,greater<int> >QU;//小根堆
typedef long long ll;
int n;
int a[310000];
ll pmx[310000],qmn[310000],smx,smn,ans=-(1ll<<60);
int main(){
scanf("%d",&n);
for(int i=1;i<=3*n;i++){
scanf("%d",&a[i]);
}for(int i=1;i<=n;i++){
smx+=a[i];
QU.push(a[i]);
}
pmx[n]=smx;
for(int i=n+1;i<=2*n;i++){
if(a[i]>QU.top()){
smx-=QU.top();
QU.pop();
smx+=a[i];
QU.push(a[i]);
}
pmx[i]=smx;
}
for(int i=3*n;i>2*n;i--){
smn+=a[i];
QD.push(a[i]);
}
qmn[2*n+1]=smn;
for(int i=2*n;i>=n;i--){
if(a[i]<QD.top()){
smn-=QD.top();
QD.pop();
smn+=a[i];
QD.push(a[i]);
}
qmn[i]=smn;
}
for(int i=n;i<=2*n;i++){
ans=max(ans,pmx[i]-qmn[i+1]);
}
printf("%lld\n",ans);
return 0;
}