Fake Maxpooling

Fake Maxpooling

题意:

给你一个矩阵 矩阵的值为 行与列的坐标的lcm, 问子矩阵为k的所有子矩阵的最大值之和。

题解:

A:这题数据有问题吧!! 瞎搞都能过。

B:嗯嗯 比如 20 15 2 这组数据就可hack 30% 的人了, 这题正确的做法用单调队列或者滑动窗口, 是个模板题。

A:能解释下吗?

B:单调队列 先扫描每一行, 维护 递减, 然后判断 队列的首项 是否 > j - k 如果是 那么 这个子矩阵的行的最大值就是 \(mp[i][q.front()]\) 否则就删除首项。 然后再维护一边 列,就可求出每个子矩阵的最大值了。

A:没听懂!!!

B:那就看我的代码模拟一边。

A: 好的!

#include<bits/stdc++.h>

using namespace std;

typedef long long ll;

int n, m, k;
int mp[5007][5007];

int lcm(int x, int y) {
    return x * y / __gcd(x, y);
}

int maxn[5007][5007];
deque<int>q;
int main () {
    scanf("%d %d %d", &n, &m, &k);
    ll sum = 0;
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            mp[i][j] = lcm(i, j);
        }
    }

    for (int i = 1; i <= n; i++) {
        q.clear();
        for (int j = 1; j <= m; j++) {
            while (!q.empty() && mp[i][q.front()] < mp[i][j]) {
                q.pop_back();
            }
            q.push_back(j);
            while(!q.empty() && q.front() <= j - k) {
                q.pop_front();
            }
            maxn[i][j] = mp[i][q.front()];
        }
    }


    for (int i = 1; i <= m; i++) {
        q.clear();
        for (int j = 1; j <= n; j++) {
            while (!q.empty() && maxn[q.front()][i] < maxn[j][i]) {
                q.pop_back();
            }
            q.push_back(j);
            while(!q.empty() && q.front() <= j - k) {
                q.pop_front();
            }
            mp[j][i] = maxn[q.front()][i];
        }
    }

    ll ans = 0;
    for (int i = k; i <= n; i++) {
        for (int j = k; j <= m; j++) {
            ans += mp[i][j];
        }
    }
    printf("%lld\n", ans);


    


}
posted @ 2020-07-14 01:10  ccsu_zhaobo  阅读(65)  评论(0编辑  收藏  举报