CodeForces 446B DZY Loves Modification

来源:互联网 发布:getscript 获得js源码 编辑:程序博客网 时间:2024/05/22 16:53

题意:

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 1000010typedef __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\n",ans);    return 0;}


0 0