济南学习 Day 3 T3 am

选数字 (select)
Time Limit:3000ms Memory Limit:64MB
题目描述
LYK 找到了一个 n*m 的矩阵,这个矩阵上都填有一些数字,对于第 i 行第 j 列的位置上
的数为 ai,j。
由于它 AK 了 noip2016 的初赛,最近显得非常无聊,便想到了一个方法自娱自乐一番。
它想到的游戏是这样的: 每次选择一行或者一列, 它得到的快乐值将会是这一行或者一列的
数字之和。之后它将该行或者该列上的数字都减去 p(之后可能变成负数) 。如此,重复 k
次,它得到的快乐值之和将会是它 NOIP2016 复赛比赛时的 RP 值。
LYK 当然想让它的 RP 值尽可能高,于是它来求助于你。
输入格式(select.in)
第一行 4 个数 n,m,k,p。
接下来 n 行 m 列,表示 ai,j。
输出格式(select.out)
输出一行表示最大 RP 值。
输入样例
2 2 5 2
1 3
2 4
输出样例
11
数据范围
总共 10 组数据。
对于第 1,2 组数据 n,m,k<=5。
对于第 3 组数据 k=1。
对于第 4 组数据 p=0。
对于第 5,6 组数据 n=1,m,k<=1000。
对于第 7,8 组数据 n=1,m<=1000,k<=1000000。
对于所有数据 1<=n,m<=1000,k<=1000000,1<=ai,j<=1000,0<=p<=100。
样例解释
第一次选择第二列,第二次选择第二行,第三次选择第一行,第四次选择第二行,第五
次选择第一行,快乐值为 7+4+2+0+-2=11。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<queue>
 5 using namespace std;
 6 #define INF 100000000000000LL
 7 #define ll long long
 8 #define R register
 9 priority_queue<int> q1,q2;
10 ll xx[1000100],yy[1000100],x[1100],y[1100];
11 ll n,m,k,p,ans;
12 void anwser()
13 {
14     xx[0]=0;yy[0]=0;
15     for(ll i=1;i<=n;i++)
16       q1.push(x[i]);
17     for(ll i=1;i<=k;i++)
18     {
19         R ll t=q1.top();
20         xx[i]=xx[i-1]+t;
21         q1.pop();
22         q1.push(t-p*m);
23     }
24     for(int j=1;j<=m;j++)
25       q2.push(y[j]);
26     for(ll i=1;i<=k;i++)
27     {
28         R ll t=q2.top();
29         yy[i]=yy[i-1]+t;
30         q2.pop();
31         q2.push((t-p*n));
32     }
33     ans=-INF;
34     for(int i=1;i<=k;i++)
35       ans=max(ans,xx[i]+yy[k-i]-p*(k-i)*i);
36     
37 }
38 int main()
39 {
40     scanf("%d%d%d%d",&n,&m,&k,&p);
41     for(int i=1;i<=n;i++)
42     {
43         for(int j=1;j<=m;j++)
44         {
45             ll xxx;
46             scanf("%ll",&xxx);
47             x[i]+=xxx;
48             y[j]+=xxx;
49         }
50     }
51     anwser();
52     
53     printf("%d",ans);
54     
55     return 0;
56 }

 

思路:首先我们可以得知如果你选择了i行,则你一定选择了k-i列,我们对每一行每一列都处理出一个前缀和,然后只要是这i行和这(k-i)列,答案一定最优,和选取顺序无关

那么,再开两个数组,用堆维护一下就可以了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

七情六欲·

学生党不容易~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值