首页 > 代码库 > Codeforces 446B DZY Loves Modification 矩阵行列分开考虑 优先队列+构造
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 提出来,那么选行和选列就互不影响
就可以分别考虑行和列
对于只取行的情况:
预处理出选0次 1次······k次行的最大值 H[i]
即优先队列跑一次即可
同理对列处理, 得到 L[i] 表示取i次列, 0次行的最大值
然后 ans = max( H[i]+L[k-i] - i*(k-i)*p )
注意结果可能是很小的负数,ans = -inf ,inf要足够大
#include <cstdio> #include <algorithm> #include<iostream> #include<string.h> #include <math.h> #include<queue> using namespace std; #define ll long long #define N 1005 #define M 1000005 ll a[N][N]; ll retc[M], retr[M]; priority_queue<pair<ll, ll> > sc, sr; int main() { ll n, m, k, p; while(cin>>n>>m>>k>>p){ while(!sc.empty())sc.pop(); while(!sr.empty())sr.pop(); for(ll i = 1; i <= n; i ++) { for(ll j = 1; j <= m; j ++) { scanf("%I64d", &a[i][j]); } } for(ll i = 1; i <= n; i ++) { ll s = 0; for(ll j = 1; j <= m; j ++) { s += a[i][j]; } sr.push(make_pair(s, i)); } for(ll j = 1; j <= m; j ++) { ll s = 0; for(ll i = 1; i <= n; i ++) { s += a[i][j]; } sc.push(make_pair(s, j)); } for(ll i = 1; i <= k; i ++) { ll s = sr.top().first; ll id = sr.top().second; retr[i] = retr[i-1] + s; s -= p*m; sr.pop(); sr.push(make_pair(s, id)); } for(ll i = 1; i <= k; i ++) { ll s = sc.top().first; ll id = sc.top().second; retc[i] = retc[i-1] + s; s -= p*n; sc.pop(); sc.push(make_pair(s, id)); } ll ans = -(ll)(1e18); for(ll i = 0; i <= k; i ++) { ans = max(ans, retr[i] + retc[k-i] - (ll)i * (k-i) * p); } cout<<ans<<endl; } return 0; } /* 2 2 2 2 1 3 2 4 2 2 5 2 1 3 2 4 3 1 3 1 3 2 1 3 2 4 1 1 1 1 1 1 1 3 1 3 1 0 0 0 2 3 3 2 1 1 -1 -1 1 1 1 5 21 1 1 2 3 4 5 6 */
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。