CF446B DZY Loves Modification 【思维/优先队列】By cellur925

题目传送门

题目大意:给一个 \(n*m\) 的矩阵,并进行 \(k\) 次操作,每次操作将矩阵的一行或一列的所有元素的值减 \(p\) ,得到的分数为这次修改之前这一列/一行的元素和,求分数最大值。

我开始的意识流想法是用一个优先队列维护,先把所有元素插入,然后\(k\)次每次取出堆顶,减去乘\(p\)的什么东西,再塞回队中。但是...行与列是会互相影响的鸭,那么怎么搞呢?然后就不会了hh。

正解是努力打破了行与列之间的相互影响,把行与列分开计算。我们考虑行与列是怎么互相影响的:选择\(i\)个行,\(j\)个列,那么这里\(j=k-i\)。显然会产生\(i\)*\((k-i)\)个交点,我们需要另减去这些交点的贡献。

我们分别处理出行&列后,枚举最终的\(i\)就好了:)


#include<cstdio>
#include<algorithm>
#include<queue>

using namespace std;
typedef long long ll;

int n,m,k,p;
int f[2018][2018];
ll hang[2000],lie[2000],hang_cnt[1000900],lie_cnt[1000900];
ll ans=-1e18;
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",&f[i][j]);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            lie[j]+=f[i][j],hang[i]+=f[i][j];
    for(int i=1;i<=m;i++) q.push(lie[i]);
    for(int i=1;i<=k;i++)
    {
        ll tmp=q.top();q.pop();
        lie_cnt[i]=lie_cnt[i-1]+tmp;
        tmp-=1ll*n*p;
        q.push(tmp);
    }
    while(!q.empty()) q.pop();
    for(int i=1;i<=n;i++) q.push(hang[i]);
    for(int i=1;i<=k;i++)
    {
        ll tmp=q.top();q.pop();
        hang_cnt[i]=hang_cnt[i-1]+tmp;
        tmp-=1ll*m*p;
        q.push(tmp);
    }
    for(int i=0;i<=k;i++)
        ans=max(ans,hang_cnt[i]+lie_cnt[k-i]-1ll*i*(k-i)*p);
    printf("%lld\n",ans);
    return 0;
}

注意开始数组开小了==!\(k\)是\(1e5\)级别的。到现在还犯这种智障错误==。

原文地址:https://www.cnblogs.com/nopartyfoucaodong/p/9893177.html

时间: 2024-12-13 19:30:56

CF446B DZY Loves Modification 【思维/优先队列】By cellur925的相关文章

Codeforces Round #FF/#255 D DZY Loves Modification --贪心+优先队列

题意:给你一个矩阵,每次选某一行或者某一列,得到的价值为那一行或列的和,然后该行每个元素减去p.问连续取k次能得到的最大总价值为多少. 解法: 如果p=0,即永远不减数,那么最优肯定是取每行或每列那个最大的取k次,所以最优解由此推出. 如果不管p,先拿,最后再减去那些行列交叉点,因为每个点的值只能取一次,而交叉点的值被加了两次,所以要减掉1次,如果取行A次,取列B次,那么最后答案为: res = dp1[A] + dp2[B] - B*(k-A)*p,可以细细体会一下后面那部分. 其中: dp1

Codeforces Round #FF (Div. 2) D. DZY Loves Modification 贪心+优先队列

链接:http://codeforces.com/problemset/problem/447/D 题意:一个n*m的矩阵.能够进行k次操作,每次操作室对某一行或某一列的的数都减p,获得的得分是这一行或列原来的数字之和.求N次操作之后得到的最高得分是多少. 思路:首先分别统计每行和每列的数字和. 进行的k次操作中,有i次操作是对行进行操作,剩余k-i次操作是对列进行操作. 首先在操作中忽略每次操作中行对列的影响,然后计算列的时候,最后能够计算出,总共的影响是i*(k-i)*p. 找出对于每一个i

Codeforces 446B DZY Loves Modification 矩阵行列分开考虑 优先队列+构造

题目链接:点击打开链接 题意: 给定n行m列的矩阵 k次操作,一个常数p ans = 0; 对于每次操作 可以任选一行或一列, 则ans += 这行(列)的数字和 然后这行(列)上的每个数字都-=p 问最大的ans 思路: 首先我们设最终选了 行 i 次,则列选了 k-i 次 那么假设我们先全部选行,然后选列,则每次选列时,要-= i*p 这样最后是 -= i*(k-i)*p 也就是所有行对列的影响 那我们先把这个 i*(k-i)*p 提出来,那么选行和选列就互不影响 就可以分别考虑行和列 对于

[CodeForces - 447D] D - DZY Loves Modification

D - DZY Loves Modification As we know, DZY loves playing games. One day DZY decided to play with a n?×?mmatrix. To be more precise, he decided to modify the matrix with exactly koperations. Each modification is one of the following: Pick some row of

CodeForces 446B DZY Loves Modification

题意: k次操作  每次选择一行或一列  得到所选数字的和  并将所选数字同时减去p  问最多得到多少 思路: 重点在消除行列间的相互影响 由于每选一行所有列所对应的和都会-p  那么如果选了i次行  则列会-i*p  同理选列 那么影响就可以这样表示 -p*i*(k-i)  把影响提出来  这样行列就不影响了 对于行或列  单独处理时相当于一维的东西  贪心即可 代码: #include<cstdio> #include<cstring> #include<algorith

codeforces#FF(div2) D DZY Loves Modification

首先要知道选择行列操作时顺序是无关的 用两个数组row[i],col[j]分别表示仅选择i行能得到的最大值和仅选择j列能得到的最大值 这个用优先队列维护,没选择一行(列)后将这行(列)的和减去对应的np (mp)又一次增加队列 枚举选择行的次数为i,那么选择列的次数为k - i次,ans = row[i] + col[k - i] - (k - i) * i * p; 既然顺序无关,能够看做先选择完i次行,那么每次选择一列时都要减去i * p,选择k - i次列,即减去(k - i) * i *

hdu 5195 DZY Loves Topological Sorting BestCoder Round #35 1002 [ 拓扑排序 + 优先队列 || 线段树 ]

传送门 DZY Loves Topological Sorting Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 221    Accepted Submission(s): 52 Problem Description A topological sort or topological ordering of a directed

DZY Loves Topological Sorting (BC #35 hdu 5195 topsort+优先队列)

DZY Loves Topological Sorting Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Total Submission(s): 264    Accepted Submission(s): 63 Problem Description A topological sort or topological ordering of a directed gr

Codeforces 444A DZY Loves Physics(图论)

题目链接:Codeforces 444A DZY Loves Physics 题目大意:给出一张图,图中的每个节点,每条边都有一个权值,现在有从中挑出一张子图,要求子图联通,并且被选中的任意两点,如果存在边,则一定要被选中.问说点的权值和/边的权值和最大是多少. 解题思路:是图论中的一个结论,最多两个节点,所以枚举两条边就可以了.我简单的推了一下,2个点的情况肯定比3个点的优. 假设有3个点a,b,c,权值分别为A,B,C 现a-b,b-c边的权值分别为u,v 那么对于两点的情况有A+Bu,B+