趣 味 卡 常 - 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,这份代码可以从哪些方面优化时间复杂度的常数?它说:

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


浙公网安备 33010602011771号