1 条题解
-
2
贪心+模拟,我们将数组分为左右两堆,那么答案就是左边那堆的最大的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
- 上传者