问 ABC388 F
  • 板块学术版
  • 楼主chenwenmo
  • 当前回复18
  • 已保存回复18
  • 发布时间2025/1/12 00:15
  • 上次更新2025/1/12 13:32:00
查看原帖
问 ABC388 F
815504
chenwenmo楼主2025/1/12 00:15

不知道这个算法对不对,就是设 fi,jf_{i,j}gi,jg_{i, j} 分别表示 lijl_i - jri+jr_i + j 能否到达,转移就是 gifi+1g_{i} \to f_{i + 1}figif_{i} \to g_{i},状态数 O(MA)O(MA)。调了好久,一直 WA ×4\times 4

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ull = unsigned long long;

const int N = 2e4 + 5;

ll n, l[N], r[N], A, B;
int m;
bool f[N][100], g[N][100];

bool check(ll a, ll b) { // 若中间无障碍,a 能否到达 b
    if (a > b) return false;
    if (a == b) return true;
    ll len = b - a + 1;
    ll cnt = (len - 1) / A;
    ll L = a + cnt * A, R = a + cnt * B;
    if (L <= b && R >= b) return true;
    else return false;
}

int main() {
    cin >> n >> m >> A >> B;
    for (int i = 1; i <= m; i++) {
        cin >> l[i] >> r[i];
    }
    if (m == 0) {
        if (check(1, n)) cout << "Yes\n";
        else cout << "No\n";
        return 0;
    }
    if (A == B) {
        if (A == 1) {
            cout << "No\n";
            return 0;
        }
        for (int i = 1; i <= m; i++) {
            for (ll j = l[i]; j <= r[i]; j++) {
                if (j % A == 1) {
                    cout << "No\n";
                    return 0;
                }
            }
        }
        if (n % A != 1) cout << "No\n";
        else cout << "Yes\n";
        return 0;
    }
    l[0] = r[0] = 0;
    l[m + 1] = r[m + 1] = n + 1;
    for (ll i = A + 1; i <= B + 1; i++) {
        if (0 + i >= l[1]) break;
        g[0][i] = true;
    }
    g[0][1] = true;
    for (int i = 1; i <= m; i++) {
        for (ll j = 1; j <= 21; j++) {
            if (l[i] - j <= r[i - 1]) break;
            for (ll k = 1; k <= 21; k++) {
                if (r[i - 1] + k >= l[i]) break;
                if (g[i - 1][k] && check(r[i - 1] + k, l[i] - j)) {
                    f[i][j] = true;
                    break;
                }
            }
        }
        for (ll j = 1; j <= 21; j++) {
            if (r[i] + j >= l[i + 1]) break;
            for (ll k = 1; k <= 21; k++) {
                if (l[i] - k <= r[i - 1]) break;
                if (f[i][k] && l[i] - k + B >= r[i] + j && l[i] - k + A <= r[i] + j) {
                    g[i][j] = true;
                    break;
                }
            }
        }
    }
    for (ll i = 1; i <= 21; i++) {
        if (r[m] + i > n) break;
        if (g[m][i] && check(r[m] + i, n)) {
            cout << "Yes\n";
            return 0;
        }
    }
    cout << "No\n";
    return 0;
}
2025/1/12 00:15
加载中...