返回题解分享
讨论 / 题解分享/ 帖子详情

数据清洗 - 题解

贪心+模拟,我们将数组分为左右两堆,那么答案就是左边那堆的最大的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 阅读
回复 (0)
默认 最新
暂无回复,快来抢沙发!