1 条题解

  • 2
    @ 2025-4-11 17:45:05

    贪心+模拟,我们将数组分为左右两堆,那么答案就是左边那堆的最大的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;
    }
    
    • 1

    信息

    ID
    336
    时间
    1500ms
    内存
    512MiB
    难度
    8
    标签
    (无)
    递交数
    305
    已通过
    43
    上传者