1. 程式人生 > 其它 >中國大學生程式設計競賽(CCPC)網路選拔賽(重賽)

中國大學生程式設計競賽(CCPC)網路選拔賽(重賽)

Monopoly

按照官方題解所寫,本題細節較多,這裡我用\(map\)\(vector<pair<int,int>>\)維護餘數,需要注意的是,根據題解所說要找到\(\leq x\)的最大的數且位置最小,所以我對\(pair\)重定義了排序,讓第二維按從大到小排序,我的第一維存的是當前同餘字首和的值,第二維才是下標,方便排序。

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int INF = 1e17;
int32_t main(int argc, char *argv[]) {
    ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
    int T;
    cin >> T;
    while (T--) {
        int n, m;
        cin >> n >> m;
        map<int, int> vis;
        vector<int> a(n + 1), sum(n + 1);
        for (int i = 1; i <= n; ++i) {
            cin >> a[i];
            sum[i] = sum[i - 1] + a[i];
            if (!vis[sum[i]]) {
                vis[sum[i]] = i;
            }
        }
        if (sum[n] == 0) {
            while (m--) {
                int x;
                cin >> x;
                // 對0特判
                if (x == 0) {
                    cout << 0 << '\n';
                    continue;
                }
                cout << (vis[x] ? vis[x] : -1) << '\n';
            }
        }
        else {
            // 是否需要對後面的數取反
            bool rev = false;
            if (sum[n] < 0) {
                rev = true;
                for (int i = 1; i <= n; ++i) {
                    a[i] = -a[i];
                    sum[i] = sum[i - 1] + a[i];
                }
            }
            // 用pair方便後面二分查詢所以優先將值存到first
            // 取模為了安全以及對負數的考慮加上了S
            map<int, vector<pair<int, int>>> rem;
            for (int i = 1; i <= n; ++i) {
                int res = (sum[i] % sum[n] + sum[n]) % sum[n];
                rem[res].emplace_back(sum[i], i);
            }
            // 對每個餘數進行排序並加上邊界方便後面處理
            for (auto& it: rem) {
                auto& y = it.second;
                y.emplace_back(-INF, 0LL);
                sort(y.begin(), y.end(), [&](pair<int, int> A, pair<int, int> B) {
                    if (A.first == B.first) {
                        return A.second > B.second;
                    }
                    return A.first < B.first;
                });
            }
            while (m--) {
                int x;
                cin >> x;
                if (x == 0) {
                    cout << 0 << '\n';
                    continue;
                }
                if (rev) {
                    x = -x;
                }
                int res = (x % sum[n] + sum[n]) % sum[n];
                if (rem[res].size() < 1) {
                    cout << -1 << '\n';
                    continue;
                }
                auto& V = rem[res];
                // 找到<=x的最大值
                auto p = *--upper_bound(V.begin(), V.end(), make_pair(x, INF));
                if (p.first == -INF) {
                    cout << -1 << '\n';
                    continue;
                }
                int val = p.first, idx = p.second;
                cout << idx + abs(val - x) / sum[n] * n << '\n';
            }
        }
    }
    system("pause");
    return 0;
}

Jumping Monkey

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1e5 + 5;
vector<int> e[MAXN], g[MAXN];
void add(int u, int v) {
    e[u].push_back(v);
    e[v].push_back(u);
}
int fa[MAXN];
int find(int x) {
    return fa[x] == x ? x : fa[x] = find(fa[x]);
}
// x <- y
void merge(int x, int y) {
    fa[find(y)] = find(x);
}
struct Node {
    int idx, val;
    bool operator <(const Node &p) const {
        return val < p.val;
    }
} a[MAXN];
int main(int argc, char *argv[]) {
    ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
    int T = 1;
    cin >> T;
    while (T--) {
        int n;
        cin >> n;
        for (int i =  1; i <= n; ++i) {
            fa[i] = i;
            e[i].clear();
            g[i].clear();
        }
        for (int i = 1; i < n; ++i) {
            int u, v;
            cin >> u >> v;
            add(u, v);
        }
        for (int i = 1; i <= n; ++i) {
            int x;
            cin >> x;
            a[i] = {i, x};
        }
        sort(a + 1, a + n + 1);
        vector<int> vis(n + 1), dist(n + 1, 1);
        for (int i = 1; i <= n; ++i) {
            int u = a[i].idx;
            vis[u] = true;
            for (int v: e[u]) {
                if (vis[v]) {
                    v = find(v);
                    g[u].push_back(v);
                    // cout << u << ' ' << v << '\n';
                    merge(u, v);
                }
            }
        }
        function<void(int)> dfs = [&](int u) -> void {
            for (int v: g[u]) {
                dist[v] = dist[u] + 1;
                dfs(v);
            }
        };
        dfs(a[n].idx);
        for (int i = 1; i <= n; ++i) {
            cout << dist[i] << '\n';
        }
    }
    system("pause");
    return 0;
}