贪心先选列,再选行,再将交叉的减去
#include<cstdio>
#include<algorithm>
#include<queue>
#define ll long long
using namespace std;
int n,m,k,p; ll f[1999999],f2[1999999],ans=-1e16,a[1999999],b[1999999];
priority_queue<ll> q1, q2;
int main(){
freopen("select.in","r",stdin);
freopen("select.out","w",stdout);
scanf("%d%d%d%d",&n,&m,&k,&p);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
int x;
scanf("%d",&x);
a[i]+=x;
b[j]+=x;
}
for(int i=1;i<=n;i++) q1.push(a[i]);
for(int i=1;i<=m;i++) q2.push(b[i]);
for(int i=1;i<=k;i++){
ll x=q1.top();q1.pop();
f[i]=f[i-1]+x;
x-=m*p;q1.push(x);
}
for(int i=1;i<=k;i++){
ll x=q2.top();q2.pop();
f2[i]=f2[i-1]+x;
x-=n*p;q2.push(x);
}
for(int i=0;i<=k;i++) ans=max(ans,f[i]+f2[k-i]-1ll*i*(k-i)*p);
printf("%lld",ans);
}