题意:

初始有n个技能,初始等级为0,有1~m  m个技能等级,升级需要成本,当n个技能都升级到某个等级以上就会给予奖励

升级的成本和给予的奖励可能为负数,请问得到最大利润的状态下的利润是多少

题目链接:

https://ac.nowcoder.com/acm/contest/886/J

题解:

我的做法是对每个技能的升级到某个等级的费用先记录下来,就是对每个技能都做一遍前缀和,放进优先队列里面

即每个技能一个优先队列,成本最小的优先级最高

然后对全部技能再做一遍前缀和,算出全部技能都只到达某个等级时此刻的利润是多少

然后枚举等级,把该等级后的升级最多可以获得的利润(不包括升级奖励)算出来相加,减掉最小的就是答案

AC_code:

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn = 1000+10;
 
ll mapp[maxn][maxn], d[maxn], sum[maxn], Sum[maxn][maxn];
priority_queue<pair<ll, ll> > q[maxn];
 
int main() {
    int t, cas = 0;
    scanf("%d", &t);
    while(t--) {
        ll n, m;
        scanf("%lld %lld", &n, &m);
        memset(sum, 0, sizeof(sum));
        memset(Sum, 0, sizeof(Sum));
        for(int i = 1; i <= n; i++) {
            while(!q[i].empty()) {
                q[i].pop();
            }
            q[i].push(make_pair(Sum[i][0], 0));
            for(int j = 1; j <= m; j++) {
                scanf("%lld", &mapp[i][j]);
                Sum[i][j] = Sum[i][j-1] - mapp[i][j];
                q[i].push(make_pair(Sum[i][j], j));
                sum[j] -= mapp[i][j];
            }
        }
        d[0] = 0;
        for(int i = 1; i <= m; i++) {
            scanf("%lld", &d[i]);
            d[i] += d[i-1];
            sum[i] += sum[i-1];
        }
        ll ans = 0;
        ll tmp = 0;
        for(int k = 0; k <= m; k++) {
            tmp = d[k];
            ll maxx = tmp + sum[k];
            ll b = 0,h = 0,minn;
            for(int i = 1; i <= n; i++) {
                while(!q[i].empty() && q[i].top().second < k) {
                    q[i].pop();
                }
                b = q[i].top().first - Sum[i][k];
                if(i == 1) {
                    minn = b;
                } else {
                    minn = min(minn, b);
                }
                h += b;
            }
            ans = max(ans, maxx + h - minn);
        }
        printf("Case #%d: %lld\n", ++cas, ans);
    }
}