[Algo Beat Contest 002 E]题解
AFO_orchardist · · 题解
首先易得一个结论:所有操作都在同一个数组上进行,一定可以得到最优解之一。证明如下:
假设有两个数组,两次操作。对第一个数组第一次操作对答案的贡献为
因此现在问题变为:一次操作,将某一个数组中的所有数增加
当
当
令
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e5+5;
int n,m,q,k,b[N],l[N],tot,cur,ans=-1e18,sum;
vector<int> a[N],era,ins;
multiset<int> S;
void work1(){
sort(b+1,b+tot+1,greater<int>());
for(int i=1;i<=m;i++)
S.insert(b[i]),cur+=b[i];
int ncur=cur;
for(int i=1;i<=n;i++){
era.clear();
ins.clear();
for(int j=1;j<=l[i];j++)
if(a[i][j]+q*k>*S.begin()){
int tmp=max(*S.begin(),a[i][j]);
cur=cur+a[i][j]+q*k-tmp;
S.erase(S.find(tmp));
era.push_back(tmp);
S.insert(a[i][j]+q*k);
ins.push_back(a[i][j]+q*k);
}
ans=max(ans,cur);
cur=ncur;
for(auto v:era) S.insert(v);
for(auto v:ins) S.erase(S.find(v));
}
cout<<ans;
}
void work2(){
sort(b+1,b+tot+1);
for(int i=1;i<=tot-m;i++)
S.insert(-b[i]),cur+=b[i];
int ncur=cur;
for(int i=1;i<=n;i++){
if(m==tot){
ans=max(ans,sum+l[i]*q*k);
continue;
}
era.clear();
ins.clear();
for(int j=1;j<=l[i];j++)
if(a[i][j]+q*k<-*S.begin()){
int tmp=min(-*S.begin(),a[i][j]);
cur=cur+a[i][j]+q*k-tmp;
S.erase(S.find(-tmp));
era.push_back(-tmp);
S.insert(-a[i][j]-q*k);
ins.push_back(-a[i][j]-q*k);
}
ans=max(ans,sum+l[i]*q*k-cur);
cur=ncur;
for(auto v:era) S.insert(v);
for(auto v:ins) S.erase(S.find(v));
}
cout<<ans;
}
signed main(){
cin>>n>>m>>q>>k;
for(int i=1;i<=n;i++){
a[i].push_back(0);
scanf("%lld",&l[i]);
for(int j=1,x;j<=l[i];j++){
scanf("%lld",&x);
a[i].push_back(x);
b[++tot]=x;
sum+=x;
}
}
if(k>0) work1();
else work2();
return 0;
}