牛客多校第6场J题 Upgrading Technology

Upgrading Technology

【思路】:

我的想法是先处理出n行的ST表,然后按照预处理出选择1~m等级的最小花费
然后O(n * m * log(m))的处理出ST表,然后O(n * m)枚举更新答案,然后愉快
的wa了3个小时,没有考虑到等级可以为0.然后特殊处理一下这种情况就可以
ac本题

ST表处理的是[l, r]里的前缀和的最小花费

附上代码:

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1005;
long long arr[MAXN][MAXN];
long long st[MAXN][1010][20]; //st表
long long value[MAXN];
long long sums[MAXN];
int n, m;
void Init()
{
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < m; j++)
        {
            st[i][j][0] = arr[i][j];
        }
    }
    for (int z = 0; z < n; z++)
    {
        for (int j = 1; (1 << j) <= m; j++)
        {
            for (int i = 0; i + (1 << j) - 1 < m; i++)
                st[z][i][j] = min(st[z][i][j - 1], st[z][i + (1 << (j - 1))][j - 1]);
        }
    }
}
long long search(int step, int l, int r)
{
    int k = (int)(log((double)(r - l + 1)) / log(2.0));
    return min(st[step][l][k], st[step][r - (1 << k) + 1][k]);
}
int main()
{

    int T;
    scanf("%d", &T);
    int cnt = 0;
    while (T--)
    {
        scanf("%d%d", &n, &m);
        for (int i = 0; i < n; i++)
        {
            for (int j = 0; j < m; j++)
            {
                scanf("%lld", &arr[i][j]);
                if(j > 0){
                    arr[i][j] = arr[i][j - 1] + arr[i][j];
                }
            }
        }
        for (int i = 0; i < m; i++)
        {
           scanf("%lld", &value[i]);
            if (i > 0)
            {
                value[i] = value[i] + value[i - 1];
            }
        }
        Init();
        long long res = 0;
        for(int i = 0; i < n; i ++){
            res += min(search(i, 0, m - 1), 0LL);
        }
        for (int i = 0; i < m; i++)
        {
            long long ans = 0;
            for (int j = 0; j < n; j++)
            {
                ans += search(j, i, m - 1);
            }
            sums[i] = ans;
        }
        long long re = 0;
        for (int i = 0; i < n; i++)
        {
            long long ans = 0;
            for (int j = 0; j < m; j++)
            {
                ans = sums[j] - search(i, j, m - 1) + arr[i][j];
                re = max(re, value[j] - ans);
            }
        }
        for (int i = 0; i < n; i++)
        {
            long long ans = res - min(search(i, 0, m - 1), 0LL) + 0LL;
            re = max(-ans, re);
        }
        printf("Case #%d: %lld\n", ++cnt, re);
    }
    return 0;
}

posted @ 2019-08-04 15:56  moxin0509  阅读(112)  评论(0编辑  收藏  举报