Codeforces #447 Div2 D

D. DZY Loves Modification

Description

As we know, DZY loves playing games. One day DZY decided to play with a n × m matrix. To be more precise, he decided to modify the matrix with exactly k operations.

Each modification is one of the following:

Pick some row of the matrix and decrease each element of the row by p. This operation brings to DZY the value of pleasure equal to the sum of elements of the row before the decreasing.
Pick some column of the matrix and decrease each element of the column by p. This operation brings to DZY the value of pleasure equal to the sum of elements of the column before the decreasing.
DZY wants to know: what is the largest total value of pleasure he could get after performing exactly k modifications? Please, help him to calculate this value.

Input

The first line contains four space-separated integers n, m, k and p (1 ≤ n, m ≤ 103; 1 ≤ k ≤ 106; 1 ≤ p ≤ 100).
Then n lines follow. Each of them contains m integers representing aij (1 ≤ aij ≤ 103) — the elements of the current row of the matrix.

Output

Output a single integer — the maximum possible total pleasure value DZY could get.

Sample Input

2 2 2 2
1 3
2 4

Sample Output

11

Hint
题意 :

一个n*m的矩阵,每次可以选择一行或者一列得到这行或列的数字总和的分数,然后将选择的行列中每个数减去p,问进行k此操作后得到的最大分数是多少。

题解 :

(1) :因为每一行或列是可以重复选择的,将每行和列的总和放进一个堆里,然后每次取出堆顶最大值,用ans累计,统计取出的行和列的个数 i i j j ,再把更新过后的数值再放进堆中,因为行和列会有重复选择所以将 a n s = i × ( k i ) × p ans-=i×(k-i)×p
(2) :这样会有一个问题,当有一行和一列的数值相等且是最大时,选择其中一个可能会导致错误 (实质是因为选行和列的次数是动态的) ,所以我们不直接把行和列放入一个堆中,而是枚举对行和列操作的次数,用数组记录对行操作 i i 次最大值为 X [ i ] X[i] ,对列操作 i i 次最大值为 Y [ i ] Y[i] ,最终答案就为 a n s = m a x ( a n s , X [ i ] + Y [ k i ] i ( k i ) p ) ans=max(ans,X[i]+Y[k-i]-i*(k-i)*p)

代码 :
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N=1e6+7,inf=1e18+7;
int n,m,k,p,x;
ll r[N],c[N],X[N],Y[N];
priority_queue<ll> Q;
int main() {
    scanf("%d%d%d%d",&n,&m,&k,&p);
    for (int i=1;i<=n;i++) {
        for (int j=1;j<=m;j++) {
            scanf("%d",&x);
            r[i]+=x; c[j]+=x;
        }
    }
    for (int i=1;i<=n;i++) Q.push(r[i]);
    for (int i=1;i<=k;i++) {
        ll num=Q.top(); Q.pop();
        X[i]=X[i-1]+num;
        num-=m*p;
        Q.push(num);
    }
    while (!Q.empty()) Q.pop();
    for (int i=1;i<=m;i++) Q.push(c[i]);
    for (int i=1;i<=k;i++) {
        ll num=Q.top(); Q.pop();
        Y[i]=Y[i-1]+num;
        num-=n*p;
        Q.push(num);
    }
    ll ans=-inf;
    for (int i=0;i<=k;i++) {
        ans=max(ans,X[i]+Y[k-i]-1ll*i*(k-i)*p);
    }
    printf("%lld\n",ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_42149421/article/details/86663596