Codeforces Round 1038, Div. 1 + Div. 2 (A-E)

C

一维的时候分成两组,二维的时候怎么办?
我们发现只考虑一维时sort后把前半部分和后半部分的点随机匹配结果都是相同的,也是最优的。
二维按x,y分为四个部分,刚好四个部分也是可以两个部分两个部分匹配的!(通过a+b=b+c可证a=c)

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define int long long
#define endl '\n'
const int N = 2e5 + 8;
struct Node{
    int x, y, id;
}p[N];
bool cmp(const Node &x, const Node &y) {
    if (x.x != y.x) return x.x < y.x;
    return x.y < y.y;
}
bool cmp2(const Node &x, const Node &y) {
    if (x.y != y.y) return x.y < y.y;
    return x.x < y.x;
}
void solve() {
    int n, m;
    cin >> n;
    for (int i = 1; i <= n; i++) 
        p[i].id = i, cin >> p[i].x >> p[i].y;
    sort(p + 1, p + n + 1, cmp);
    for (int i = 1; i <= n; i++) {
        if (i <= n / 2) p[i].x = 0;
        else p[i].x = 1;
    }
    sort(p + 1, p + n + 1, cmp2);
    //{00} {01} {10} {11}
    vector<int> a, b, c, d;
    for (int i = 1; i <= n; i++) {
        if (!p[i].x) {
            if (i <= n / 2) a.push_back(p[i].id);
            else b.push_back(p[i].id);
        }
        else {
            if (i > n / 2) c.push_back(p[i].id);
            else d.push_back(p[i].id);
        }
    }
    // cout << a.size() << ' ' << c.size() << endl;
    // return;
    // cout << "XXX" << endl;
    for (int i = 0; i < a.size(); i++) {
        cout << a[i] << ' ' << c[i] << endl;
    }
    for (int i = 0; i < b.size(); i++) {
        cout << b[i] << ' ' << d[i] << endl;
    }
}
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int T;
    cin>>T;
    while(T--){
        solve();
    }
}

D

一眼bfs拆点dp。但是需要满足的最优状态有t和wait t两维复杂度太高做不到。
猜测t最高为2*n,(已有大佬证明了t最大为2n-3),那么只需要维护wait t最优即可不断转移,n方可做

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define int long long
#define endl '\n'
const int N = 5e3 + 9;
struct Node{
    int x, y, id;
}p[N];
bool cmp(const Node &x, const Node &y) {
    if (x.x != y.x) return x.x < y.x;
    return x.y < y.y;
}
vector<int> E[N];
void solve() {
    int n, m;
    cin >> n >> m;
    vector<vector<int>> E(n + 1);
    for (int i = 1; i <= m; i++) {
        int u, v;
        cin >> u >> v;
        E[u].push_back(v);
        E[v].push_back(u);
    }
    vector<int> f(n + 1, 0x3f3f);
    f[1] = 0;
    for (int t = 0; t < 2 * n; t++) {
        // cout << t << "XXX" << endl;
        if (f[n] != 0x3f3f) {
            cout << t << ' ' << f[n] << endl;
            return;
        }
        vector<int> tf(n + 1, 0x3f3f);
        for (int i = 1; i <= n; i++) {
            int c = E[i].size();
            int v = E[i][t % c];
            tf[i] = min(tf[i], f[i] + 1);
            tf[v] = min(tf[v], f[i]);
        }
        swap(f, tf);
    }
}
signed main()
{
    // ios::sync_with_stdio(false);
    // cin.tie(nullptr);
    int T;
    cin>>T;
    while(T--){
        solve();
    }
}

E

看tourist代码学习而得。
如果新的\({c_i}\)小于0那么就重置,否则就更新

#include<bits/stdc++.h>
using namespace std;
#define ll long long
// #define int long long
#define endl '\n'
const int N = 2e5 + 8;
const int mod = 998244353; 
int add(int x) {return x > mod ? x - mod : x;}
int mul(int x, int y) {return (1ll * x * y % mod);}
int a[2][N];
void solve() {
    int n, k;
    cin >> n >> k;
    for (int i = 0; i < 2; i++) {
        for (int j = 0; j < n; j++) {
            cin >> a[i][j];
        }
    }
    vector<int> f(k + 1, 0);
    f[k] = 1;
    for (int i = 1; i < n; i++) {
        vector<int> w(2* k+1, 0);
        for (int x = 1; x <= k; x++) {
            if (x != -1 && a[0][i] != -1 && x != a[0][i]) continue;
            for (int y = 1; y <= k; y++) {
                if (y != -1 && a[1][i - 1] != -1 && a[1][i - 1] != y) continue;
                w[x - y + k]++;
            }  
        }
        vector<int> tf(k + 1, 0);
        for (int p = 0; p <= k; p++) {
        // cout << p << endl;
            if (f[p] == 0) continue;
            int tp = p;
            for (int d = -k + 1; d <= k - 1; d++) {
                if (p == k) {
                    if (d >= 0) 
                        tp = k;
                    else 
                        tp = -d;
                }
                else {
                    if (p - d < 0) continue;
                    if (d < 0) tp = -d;
                    else tp = p - d;
                }
                assert(tp >= 0 && tp <= k);
                tf[tp] = add(tf[tp] + mul(f[p], w[d + k]));
            }
        }
        swap(f, tf);
    }
    int ans = 0;
    for (int i = 0; i <= k; i++) ans = add(ans + f[i]);
    if (a[0][0] == -1) ans = mul(ans, k);
    if (a[1][n - 1] == -1) ans = mul(ans, k);
    cout << ans << endl;

}
signed main()
{
    // ios::sync_with_stdio(false);
    // cin.tie(nullptr);
    int T;
    cin>>T;
    while(T--){
        solve();
    }
}
posted @ 2025-07-20 15:20  lyrrr  阅读(86)  评论(0)    收藏  举报