[模拟]AT_abc433_e [ABC433E] Max Matrix 2 题解

这个 \(\max\) 的限制很烦,因此需要处理。

可以倒序枚举数字,从 \(n \times m\)\(1\)。这样就保证了放下的每个数字都不会被后面的数字影响。

对于一个 \([1, n \times m]\) 的数字 \(x\)

  • 如果存在一个 \(X_i = Y_j = x\), 那么 \(x\) 只能放在 \(i, j\) 的位置。

  • 如果只存在一个 \(X_i = x\),那么 \(x\) 放在 \(i\) 行的某一列。

    而为了满足题目条件,它放的这一列上必须已经有了数(由于倒叙枚举,这个数一定比 \(x\) 大,\(x\) 不会对这一列产生影响)。否则 \(x\) 就会成为这一列最大的,导致不合题意。

  • 如果只存在一个 \(Y_i = x\),那么同上一种情况。

  • 如果都不存在,那么 \(x\) 可以放在任意一个行和列都已经有数的位置(倒序枚举,已有数都比它大,它不产生影响)。

然后我们发现对于情况 2 和 3,我们并不需要 \(x\) 产生影响(因为他所在的行和列都有数了,而且这些数都比他大),只要能放下就行。因此只要满足条件,其实放哪都行。

一个重要的发现是,数字 \(n \times m\) 是一定能确定位置的,因为一定存在 \(X_i = n \times m, Y_j = n \times m\)(否则无解)。

于是我们记录 \(n \times m\) 数字放置的坐标为 \(fx, fy\)

所以对于情况 2,我们可以把 \(x\) 放在 \(i, fy\)

对于情况 3,可以放在 \(fx, j\)

然后处理一下情况 4。其实我们每确定一个数字,就用他更新一下可以放置的地点就可以。因为一共 \(n \times m\) 个位置,因此复杂度没问题。

最后判一下就好了。

#include <bits/stdc++.h>
#define int long long
#define rep(i, a, b) for(register int i = a; i <= b; ++i)
#define rep_(i, a, b) for(register int i = a; i >= b; --i)
using namespace std;
int t;
constexpr int N = 2e5 + 5;
namespace Kx {
    bool vis[N];
	int n, m, x[N], y[N], a[N], b[N], maxh[N], maxl[N];
    vector<int> qdh, qdl;
    vector<vector<int>> ans;
    vector<pair<int, int>> free; 
	void main() {
		cin >> n >> m;
		ans.clear();
		ans.resize(n + 1);
        rep(i, 1, n * m) {
            a[i] = b[i] = vis[i] = 0;
        }
        qdh.clear(), qdl.clear(), free.clear();
        rep(i, 1, n) {
            ans[i].resize(m + 1);
            maxh[i] = 0;
        }
        rep(i, 1, m) {
        	maxl[i] = 0;
		}
		rep(i, 1, n) {
            cin >> x[i];
            a[x[i]] = i;
        }
		rep(i, 1, m) {
            cin >> y[i];
            b[y[i]] = i;
        }
        if(!a[n * m] || !b[n * m]) {
        	cout << "No" << '\n';
        	return;
		}
        ans[a[n * m]][b[n * m]] = n * m;
        qdh.push_back(a[n * m]);
        qdl.push_back(b[n * m]);
		rep_(i, n * m - 1, 1) {
			if(a[i] && b[i]) {
                ans[a[i]][b[i]] = i;
                for(const int y : qdl) {
                    if(!ans[a[i]][y]) {
                        free.push_back(make_pair(a[i], y));
                    }
                }
                for(const int x : qdh) {
                    if(!ans[x][b[i]]) {
                        free.push_back(make_pair(x, b[i]));
                    }
                }
                qdh.push_back(a[i]);
                qdl.push_back(b[i]);

            }
            else if(a[i] && !b[i]) {
                ans[a[i]][b[n * m]] = i;
                for(const int y : qdl) {
                    if(!ans[a[i]][y]) {
                        free.push_back(make_pair(a[i], y));
                    }
                }
                qdh.push_back(a[i]);
            }
            else if(!a[i] && b[i]) {
                ans[a[n * m]][b[i]] = i;
                for(const int x : qdh) {
                    if(!ans[x][b[i]]) {
                        free.push_back(make_pair(x, b[i]));
                    }
                }
                qdl.push_back(b[i]);
            }
            else {
                if(free.size()) {
                    ans[free.back().first][free.back().second] = i;
                    free.pop_back();
                }
                else {
                	cout << "No" << '\n';
                	return;
				}
            }
		}
        rep(i, 1, n) {
            rep(j, 1, m) {
                if(vis[ans[i][j]] || ans[i][j] > n * m || ans[i][j] < 1) {
                    cout << "No" << '\n';
                    return;
                }
                vis[ans[i][j]] = true;
            }
        }
        rep(i, 1, n) {
            rep(j, 1, m) {
                maxh[i] = max(maxh[i], ans[i][j]);
                maxl[j] = max(maxl[j], ans[i][j]);
            }
        }
        rep(i, 1, n) {
            if(maxh[i] != x[i]) {
                cout << "No" << '\n';
                return;
            }
        }
        rep(i, 1, m) {
            if(maxl[i] != y[i]) {
                cout << "No" << '\n';
                return;
            }
        }
        cout << "Yes" << '\n';
        rep(i, 1, n) {
            rep(j, 1, m) {
                cout << ans[i][j] << ' ';
            }
            cout << '\n';
        }
	}
}
signed main() {
    //freopen("in.txt", "r", stdin);
    //freopen("out.txt", "w", stdout);
    ios :: sync_with_stdio(0), cin.tie(0), cout.tie(0);
	cin >> t;
	while(t--) {
		Kx :: main();
	}
	return 0;
}

posted @ 2025-11-29 11:58  __Kx  阅读(1)  评论(0)    收藏  举报