abc F求调
  • 板块学术版
  • 楼主oOoOoOOOooOO
  • 当前回复0
  • 已保存回复0
  • 发布时间2025/1/12 11:51
  • 上次更新2025/1/12 16:55:37
查看原帖
abc F求调
42324
oOoOoOOOooOO楼主2025/1/12 11:51

我的做法是考虑把所有不可走的段的左右两边可以走的50个点取出来。然后对于每个点往[a, b]可以走的点建边,然后对于可走段的两端的50个点,用同余最短路判断是否可达。最后dfs检查1 n是否连通

#include <iostream>
#include <vector>
#include <unordered_map>
#include <algorithm>
#include <cstring>
#include <queue>
#include <set>
#include <cmath>
#include <random>
#include <tuple>
#include <numeric>
#include <map>
#include <iomanip>
#include <cassert>
#include <bitset>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;

const int N = 2e4 + 5;

ll dis[25];

ll L[N], R[N];

vector<ll> Ls[N], Rs[N];

unordered_map<ll, vector<ll>> to;
unordered_map<ll, bool> ms;

bool dfs(ll u, ll tag)
{
    if (u == tag) return true;
    if (ms.count(u)) return ms[u];

    for(auto v : to[u]) {
        if (dfs(v, tag)) {
            return ms[u] = true;
        }
    }
    return ms[u] = false;
}

int main()
{
#ifdef local
    freopen("in.txt", "r", stdin);
#endif // local
    ios::sync_with_stdio(false);
    cin.tie(0);
    ll n, m, a, b;
    cin >> n >> m >> a >> b;
    memset(dis, 0x3f, sizeof(dis));
    dis[0] = 0;
    queue<int> q;
    q.push(0);
    while(!q.empty())
    {
        int u = q.front();
        q.pop();
        for(int i = a; i <= b; i++)
        {
            int v = (u + i) % a;
            if (dis[v] > dis[u] + i)
            {
                dis[v] = dis[u] + i;
                q.push(v);
            }
        }
    }
    R[0] = 0;
    L[m + 1] = n + 1;
    for(int i = 1; i <= m; i++)
    {
        cin >> L[i] >> R[i];
    }
    for(int i = 1; i <= m; i++)
    {
        for(int j = L[i] - 1, z = 50; z >= 0 && j > R[i - 1]; z--, j--)
        {
            Ls[i].push_back(j);
        }
        for(int j = R[i] + 1, z = 50; z >= 0 && j < L[i + 1]; z--, j++)
        {
            Rs[i].push_back(j);
        }
    }
    Rs[0].push_back(1);
    Ls[m + 1].push_back(n);
    for(int i = 0; i <= m; i++) {
        for(auto v : Ls[i]) {
            for(int w = a; w <= b; w++) {
                ll now = v + w;
                int mk = 0;
                for(int k = max(1, i); k <= m; k++) {
                    if (L[k] <= now && now <= R[k]) {
                        mk = 1;
                        break;
                    }
                    if (L[k] > now) break;
                }
                if (!mk) {
                    to[v].push_back(now);
                }
            }
        }
        for(auto v : Rs[i]) {
            for(int w = a; w <= b; w++) {
                ll now = v + w;
                int mk = 0;
                for(int k = max(1, i); k <= m; k++) {
                    if (L[k] <= now && now <= R[k]) {
                        mk = 1;
                        break;
                    }
                    if (L[k] > now) break;
                }
                if (!mk) {
                    to[v].push_back(now);
                }
            }
        }
        for(auto u1 : Rs[i]) {
            for(auto v1 : Ls[i + 1]) {
                if (u1 < v1) {
                    ll d = v1 - u1;
                    if (dis[d % a] <= d) {
                        to[u1].push_back(v1);
                    }
                }
            }
        }
    }
    if (dfs(1, n)) {
        cout << "Yes" << endl;
    }
    else {
        cout << "No" << endl;
    }

    return 0;

}

2025/1/12 11:51
加载中...