贪心+模拟,我们将数组分为左右两堆,那么答案就是左边那堆的最大的n个数之和减去后面那堆最小的n个数之和,由题目意思易得,左边那堆和右边那堆数都至少有n个数字,于是我们可以先把前n个数放入左边,后2*n个数放入右边,然后再把右边不需要的数放入容器cc中,然后我们从n+1开始遍历对于每一个数,如果他在cc中出现了,那么就将这个数从cc中删除,如果他替换左边的最小值会使答案更优则将他替换,如果该数没有在cc出现,那么他一定在bb中出现了,则将该数从bb中删除,后选取cc中最小的数放入bb......
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e6+10;
int a[N];
multiset<int>aa,bb,cc;
signed main()
{
int n,ans=-1e18,sum=0;
cin>>n;
for(int i=1;i<=3*n;i++)
{
cin>>a[i];
if(i<=n)aa.insert(a[i]);
else bb.insert(-a[i]);
}
while(bb.size()>n)
{
auto xx=*bb.begin();
cc.insert(-xx);
bb.erase(bb.begin());
}
for(auto xx:aa)sum+=xx;
for(auto xx:bb)sum+=xx;
ans=max(ans,sum);
for(int i=n+1;i<=2*n;i++)
{
int x=a[i];
auto j=cc.lower_bound(x);
if(j!=cc.end()&&*j==x)
{
cc.erase(j);
auto xx=*aa.begin();
if(x>xx)
{
aa.erase(aa.begin());
aa.insert(x);
sum=sum-xx+x;
}
}
else
{
auto jj=bb.lower_bound(-x);
bb.erase(jj);
sum+=x;
auto xx=*cc.begin();
cc.erase(cc.begin());
sum-=xx;
auto yy=*aa.begin();
if(x>yy)
{
sum=sum-yy+x;
aa.erase(aa.begin());
aa.insert(x);
}
}
ans=max(ans,sum);
}
cout<<ans;
}
0 回复
0 转发
2 喜欢
3 阅读



