CodeForces 446B DZY Loves Modification

题意:

k次操作  每次选择一行或一列  得到所选数字的和  并将所选数字同一时候减去p  问最多得到多少


思路:

重点在消除行列间的相互影响

因为每选一行全部列所相应的和都会-p  那么假设选了i次行  则列会-i*p  同理选列

那么影响就能够这样表示 -p*i*(k-i)  把影响提出来  这样行列就不影响了

对于行或列  单独处理时相当于一维的东西  贪心就可以


代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
#define N 1010
#define M 1000010
typedef __int64 ll;

ll sum[2][N];
ll res[2][M];
ll ans,p;
int n,m,k;
struct node
{
    ll val;
    int x;
    bool operator<(const node fa) const
    {
        return val<fa.val;
    }
}u;
priority_queue<node> q;

int main()
{
    int i,j;
    ll w;
    scanf("%d%d%d%I64d",&n,&m,&k,&p);
    for(i=1;i<=n;i++)
    {
        for(j=1;j<=m;j++)
        {
            scanf("%I64d",&w);
            sum[0][i]+=w;
            sum[1][j]+=w;
        }
    }
    while(!q.empty()) q.pop();
    for(i=1;i<=n;i++)
    {
        u.x=i;
        u.val=sum[0][i];
        q.push(u);
    }
    for(i=1;i<=k;i++)
    {
        u=q.top();
        q.pop();
        res[0][i]=res[0][i-1]+u.val;
        u.val-=p*m;
        q.push(u);
    }
    while(!q.empty()) q.pop();
    for(i=1;i<=m;i++)
    {
        u.x=i;
        u.val=sum[1][i];
        q.push(u);
    }
    for(i=1;i<=k;i++)
    {
        u=q.top();
        q.pop();
        res[1][i]=res[1][i-1]+u.val;
        u.val-=p*n;
        q.push(u);
    }
    ans=max(res[0][0]+res[1][k],res[0][k]+res[1][0]);  // hang or lie
    for(i=1;i<k;i++) ans=max(ans,res[0][i]+res[1][k-i]-p*i*(k-i));
    printf("%I64d
",ans);
    return 0;
}


原文地址:https://www.cnblogs.com/mengfanrong/p/3877801.html