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次操作选取最高价值来计算出得到的最高分。记录为cn[i],rn[i](用优先队列取首)。

对于不同的i取ans=max(cn[i]+rn[k-i]-i*(k-i)*p)。

注意点是数据会超int,ans初始值要取得极小。

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include<queue>
#include<stack>
#include<vector>
#include<ctype.h>
#include<cstdlib>
#include<algorithm>
#include<string>
#define PI acos(-1.0)
#define maxn
typedef long long ll;
using namespace std;
long long INF =(1LL << 60);
priority_queue < long long > c,r;
int main()
{
    int n,m,k,p,x;
    long long y;
    scanf("%d%d%d%d",&n,&m,&k,&p);
    int col[1005],row[1005];
    long long cn[1000005],rn[1000005];
    for(int i=0; i<n; i++)
        for(int j=0; j<m; j++)
        {
            scanf("%d",&x);
            col[j]+=x;
            row[i]+=x;
        }
    for(int i=0; i<n; i++)
        r.push(row[i]);
    for(int i=0; i<m; i++)
        c.push(col[i]);
    cn[0]=rn[0]=0;
    for(int i=1; i<=k; i++)
    {
        y=c.top();
        cn[i]=cn[i-1]+y;
        c.pop();
        c.push(y-n*1LL*p);
        y=r.top();
        rn[i]=rn[i-1]+y;
        r.pop();
        r.push(y-m*1LL*p);
    }
    long long ans=-INF;
    for(int i=0; i<=k; i++)
        ans=max(ans,cn[i]+rn[k-i]-i*1LL*(k-i)*p);
    printf("%I64d\n",ans);
    return 0;
}
时间: 2024-08-10 03:24:06

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

DP Codeforces Round #FF (Div. 1) A. DZY Loves Sequences

题目传送门 /* DP:先用l,r数组记录前缀后缀上升长度,最大值会在三种情况中产生: 1. a[i-1] + 1 < a[i+1],可以改a[i],那么值为l[i-1] + r[i+1] + 1 2. l[i-1] + 1 3. r[i+1] + 1 //修改a[i] */ #include <cstdio> #include <algorithm> #include <cstring> using namespace std; const int MAXN =

Codeforces Round #FF (Div. 1) A. DZY Loves Sequences

原题链接:http://codeforces.com/problemset/problem/446/A 题意:给一个长度为n的序列,最多可以修改一个位置的数,求最长连续上升子序列. 题解:当a[i+1] > a[i-1]+2的时候,可以通过改变a[i]的值来使前后两段合并,反之,分别考虑a[i]作为左边那段最长的和右边那段最长的. #include <cstdio> #include <cstring> #include <algorithm> #include

Codeforces Round #FF (Div. 2) A. DZY Loves Hash

DZY has a hash table with p buckets, numbered from 0 to p?-?1. He wants to insert n numbers, in the order they are given, into the hash table. For the i-th number xi, DZY will put it into the bucket numbered h(xi), where h(x) is the hash function. In

Codeforces Round #FF (Div. 2) C - DZY Loves Sequences (DP)

DZY has a sequence a, consisting of n integers. We'll call a sequence ai,?ai?+?1,?...,?aj (1?≤?i?≤?j?≤?n) a subsegment of the sequence a. The value (j?-?i?+?1) denotes the length of the subsegment. Your task is to find the longest subsegment of a, su

Codeforces Round #FF (Div. 2) E. DZY Loves Fibonacci Numbers(斐波那契的定理+线段树)

/* 充分利用了菲波那切数列的两条定理: ①定义F[1] = a, F[2] = b, F[n] = F[n - 1] + F[n - 2](n≥3). 有F[n] = b * fib[n - 1] + a * fib[n - 2](n≥3),其中fib[i]为斐波那契数列的第 i 项. ②定义F[1] = a, F[2] = b, F[n] = F[n - 1] + F[n - 2](n≥3). 有F[1] + F[2] + -- + F[n] = F[n + 2] - b 这题还有一个事实,

Codeforces Round #FF(255) DIV2 C - DZY Loves Sequences

A - DZY Loves Hash 水题,开辟一个数组即可 #include <iostream> #include <vector> #include <algorithm> #include <string> using namespace std; int main(){ int p,n; cin >> p >> n; vector<bool> buckets(302,false); bool flag = fal

Codeforces Round #254 (Div. 2) B. DZY Loves Chemistry (并查集)

题目链接 昨天晚上没有做出来,刚看题目的时候还把题意理解错了,当时想着以什么样的顺序倒,想着就饶进去了, 也被题目下面的示例分析给误导了. 题意: 有1-n种化学药剂  总共有m对试剂能反应,按不同的次序将1-n种试剂滴入试管,如果正在滴入的试剂能与已经滴入 的试剂反应,那么危险数*2,否则维持不变.问最后最大的危险系数是多少. 分析:其实这个题根本不用考虑倒入的顺序,只是分块就行,结果就是每个子集里元素的个数-1 和  的2的幂. 1 #include <iostream> 2 #inclu

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. 1)-A,B,C

A:DZY Loves Sequences 一开始看错题了..sad. 题目很简单,做法也很简单.DP一下就好了. dp[i][0]:到当前位置,没有任何数改变,得到的长度. dp[i][1]:到当前位置,改变了一个数,得到的长度 不过需要正向求一遍,然后反向求一遍. #include<iostream> #include<stdio.h> #include<algorithm> #include<stdlib.h> #include<string.h