Loading

CF1740G 做题记录

666题 link

乍一看题,发现需要对 \(4nm\) 条路径都统计一遍,一副很不可做的样子。

但是这毕竟是构造题,我们考虑答案上界,即所有格子都取到是否可行。

这需要统计一个格子的贡献,不难想到按照 \(s_{i, j}\) 从小到大依次考虑每个格子。网格图及其连边呈现基环树状,所以可以利用并查集维护某个入口进来的起点个数以及路径上的最大值之和。

最后根据贡献多少确定 \(t_{i, j}\) 即可。


这题看着很难,事实上排个序就秒了,我分析了以下原因:

  • 构造题,最大特点是你可以自由确定某些变量或者操作,所以不必像 dp 这种考虑所有情况,只需要存在一种情况达成你所愿的。

  • 这时可以考虑答案上界,然后观察题目的特点,就能想到按 \(s_{i, j}\) 排序。

人生就像是一道构造题,如何点缀自己的生活,都是自己决定的。我们不必考虑所有的道路,去做你所愿的事吧。


点击查看代码
#include <bits/stdc++.h>
#define ll long long
#define ull unsigned ll
#define fi first
#define se second
#define mkp make_pair
#define pir pair <ll, ll>
#define pb push_back
#define i128 __int128
using namespace std;
char buf[1 << 22], *p1, *p2;
// #define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, (1 << 22) - 10, stdin), p1 == p2)? EOF : *p1++)
template <class T>
const inline void rd(T &x) {
    char ch; bool neg = 0;
    while(!isdigit(ch = getchar()))
        if(ch == '-') neg = 1;
    x = ch - '0';
    while(isdigit(ch = getchar()))
        x = (x << 1) + (x << 3) + ch - '0';
    if(neg) x = -x;
}
const ll maxn = 1010, inf = 1e9, mod = 998244353;
ll power(ll a, ll b = mod - 2) {
	ll s = 1;
	while(b) {
		if(b & 1) s = 1ll * s * a %mod;
		a = 1ll * a * a %mod, b >>= 1;
	} return s;
}
template <class T, class _T>
const inline ll pls(const T x, const _T y) { return x + y >= mod? x + y - mod : x + y; }
template <class T, class _T>
const inline void add(T &x, const _T y) { x = x + y >= mod? x + y - mod : x + y; }
template <class T, class _T>
const inline void chkmax(T &x, const _T y) { x = x < y? y : x; }
template <class T, class _T>
const inline void chkmin(T &x, const _T y) { x = x < y? x : y; }

ll n, m, a[maxn][maxn], d[maxn * maxn * 4], siz[maxn * maxn * 4], sum[maxn * maxn * 4];
pir id[maxn * maxn]; ll b[maxn][maxn];
ll Id(ll x, ll y, ll w) { return ((x - 1) * m + y - 1) * 4 + w + 1; }
ll find(ll x) { return d[x] ^ x? d[x] = find(d[x]) : x; }
void Merge(ll x, ll y) {
    x = find(x), y = find(y);
    d[x] = y, siz[y] += siz[x], sum[y] += sum[x];
}

int main() {
    rd(n), rd(m);
    for(ll i = 1; i <= n; i++)
        for(ll j = 1; j <= m; j++)
            rd(a[i][j]), id[(i - 1) * m + j] = mkp(i, j);
    sort(id + 1, id + 1 + n * m, [](pir x, pir y) {
        return a[x.fi][x.se] < a[y.fi][y.se];
    });
    for(ll i = 1; i <= 4 * n * m; i++) d[i] = i, siz[i] = sum[i] = 1;
    for(ll o = 1; o <= n * m; o++) {
        ll i = id[o].fi, j = id[o].se;
        ll s = sum[Id(i, j, 0)] + sum[Id(i, j, 1)]
         + sum[Id(i, j, 2)] + sum[Id(i, j, 3)];
        ll c = siz[Id(i, j, 0)] + siz[Id(i, j, 1)]
         + siz[Id(i, j, 2)] + siz[Id(i, j, 3)];
        ll tmp = c * a[i][j] - s; b[i][j] = tmp & 1;
        for(ll k = 0; k < 4; k++) sum[Id(i, j, k)] = a[i][j] * siz[Id(i, j, k)];
        if(tmp & 1) {
            if(j > 1) Merge(Id(i, j, 0), Id(i, j - 1, 1));
            if(i > 1) Merge(Id(i, j, 1), Id(i - 1, j, 2));
            if(j < m) Merge(Id(i, j, 2), Id(i, j + 1, 3));
            if(i < n) Merge(Id(i, j, 3), Id(i + 1, j, 0));
        } else {
            if(i < n) Merge(Id(i, j, 0), Id(i + 1, j, 0));
            if(j > 1) Merge(Id(i, j, 1), Id(i, j - 1, 1));
            if(i > 1) Merge(Id(i, j, 2), Id(i - 1, j, 2));
            if(j < m) Merge(Id(i, j, 3), Id(i, j + 1, 3));
        }
    }
    for(ll i = 1; i <= n; i++) {
        for(ll j = 1; j <= m; j++)
            printf("%lld", b[i][j]); puts("");
    }
	return 0;
}
posted @ 2025-04-01 09:24  Lgx_Q  阅读(4)  评论(0)    收藏  举报