趣 味 卡 常 - The 2022 ICPC Asia Tehran Regional Contest - F. Ammunition Storage

昨晚,我队友 frs先生 扔给我 一道题

(说这话的时候,他自己都没做!狠狠批判他!)

于是乎:



我绷不住了。上面的提交记录中,最新一次提交是这样的:

#pragma GCC optimize("O3")
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <stack>
#define int long long
const int N = 752;

int n, m, a[N][N], ans;
int lg[N], maxn[N][N][10][10], u[N], v[N], w[N];
int stk[N], tp, midmax;

inline int getmax(int xa, int ya, int xb, int yb){
    if(xa > xb || ya > yb) return 0;
    int xpw = lg[xb - xa + 1], ypw = lg[yb - ya + 1];
    return std::max({maxn[xa][ya][xpw][ypw], maxn[xb - (1 << xpw) + 1][ya][xpw][ypw], maxn[xa][yb - (1 << ypw) + 1][xpw][ypw], maxn[xb - (1 << xpw) + 1][yb - (1 << ypw) + 1][xpw][ypw]});
}

void solve() {
    std::cin >> n >> m;
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= m; j++) std::cin >> a[i][j];
    }
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= m; j++) maxn[i][j][0][0] = a[i][j];
    }
    for(int i = 1; i <= n; i++){
        for(int k = 1; k <= lg[m]; k++){
            for(int j = 1; j + (1 << k) - 1 <= m; j++){
                maxn[i][j][0][k] = std::max(maxn[i][j][0][k - 1], maxn[i][j + (1 << (k - 1))][0][k - 1]);
            }
        }
    }
    for(int j = 1; j <= m; j++){
        for(int k = 1; k <= lg[n]; k++){
            for(int i = 1; i + (1 << k) - 1 <= n; i++){
                maxn[i][j][k][0] = std::max(maxn[i][j][k - 1][0], maxn[i + (1 << (k - 1))][j][k - 1][0]);
            }
        }
    }
    for(int k = 1; k <= lg[n]; k++){
        for(int l = 1; l <= lg[m]; l++){
            for(int i = 1; i + (1 << k) - 1 <= n; i++){
                for(int j = 1; j + (1 << l) - 1 <= m; j++){
                    maxn[i][j][k][l] = std::max({maxn[i][j][k - 1][l - 1], maxn[i + (1 << (k - 1))][j][k - 1][l - 1], maxn[i][j + (1 << (l - 1))][k - 1][l - 1], maxn[i + (1 << (k - 1))][j + (1 << (l - 1))][k - 1][l - 1]});
                }
            }
        }
    }
    for(int i = 1; i < n; i++){
        for(int k = 1; k <= m; k++) w[k] = 0;
        for(int j = i + 1; j <= n; j++){
            tp = 0;
            for(int k = 1; k <= m; k++){
                if(a[i][k] > a[j][k]) u[k] = a[i][k], v[k] = a[j][k];
                else u[k] = a[j][k], v[k] = a[i][k];
                if(j - 1 > i) w[k] = std::max(w[k], a[j - 1][k]);
            }
            for(int k = 1; k <= m; k++){
                while(tp && v[stk[tp]] < w[k]) tp--;
                if(v[k] > w[k]){
                    while(tp && v[stk[tp]] < u[k]){
                        midmax = std::max({getmax(i, stk[tp] + 1, j, k - 1), w[stk[tp]], w[k]});
                        if(v[stk[tp]] > midmax && v[k] > midmax) ans++;
                        tp--;
                    }
                    if(tp){
                        midmax = std::max({getmax(i, stk[tp] + 1, j, k - 1), w[stk[tp]], w[k]});
                        if(v[stk[tp]] > midmax && v[k] > midmax) ans++;
                    }
                    stk[++tp] = k;
                    continue;
                }
                while(tp && v[stk[tp]] < u[k]) tp--;
            }
        }
    }
    std::cout << ans << "\n";
}

signed main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    std::cout.tie(nullptr);

    lg[1] = 0;
    for(int i = 2; i <= 750; i++) lg[i] = lg[i >> 1] + 1;

    int ti = 1;
    //std::cin >> ti;
    while (ti--) solve();
    return 0;
}

我问ds,这份代码可以从哪些方面优化时间复杂度的常数?它说:

靠,好像还真是。我改了一下,于是:

posted on 2025-04-25 23:46  C12AK  阅读(34)  评论(1)    收藏  举报