ylh_的博客

天梯赛L2题解(001-056)

L2-001 紧急救援

#include <bits/stdc++.h>
using namespace std;
#define int long long
using PII = pair<int, int>;

void solve() {
    int n, m, st, ed;
    cin >> n >> m >> st >> ed;
    vector<int> a(n);
    for (int i = 0; i < n; ++i) {
        cin >> a[i];
    }

    vector<vector<PII>> g(n);
    for (int i = 1; i <= m; ++i) {
        int u, v, w;
        cin >> u >> v >> w;
        g[u].push_back({ v, w });
        g[v].push_back({ u, w });
    }

    priority_queue<PII, vector<PII>, greater<PII>> pq;
    pq.push({ 0, st });

    const int INF = 1e18;
    vector<int> dist(n, INF), cnt(n, 0), sum(n, 0), pa(n, -1);
    dist[st] = 0;
    cnt[st] = 1;
    sum[st] = a[st];
    while (!pq.empty()) {
        auto [d, u] = pq.top();
        pq.pop();
        if (d > dist[u])
            continue;
        for (auto [v, w] : g[u]) {
            if (dist[v] > dist[u] + w) {
                dist[v] = dist[u] + w;
                cnt[v] = cnt[u];
                sum[v] = sum[u] + a[v];
                pa[v] = u;
                pq.push({ dist[v], v });
            } else if (dist[v] == dist[u] + w) {
                cnt[v] += cnt[u];
                if (sum[v] < sum[u] + a[v]) {
                    sum[v] = sum[u] + a[v];
                    pa[v] = u;
                }
            }
        }
    }
    cout << cnt[ed] << ' ' << sum[ed] << '\n';
    vector<int> ans;
    int cur = ed;
    while (cur != -1) {
        ans.push_back(cur);
        cur = pa[cur];
    }
    for (int i = ans.size() - 1; i >= 0; --i) {
        cout << ans[i] << (i > 0 ? " " : "");
    }
}

int32_t main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    int T = 1;
    // cin >> T;
    while (T--) {
        solve();
    }
}

L2-002 链表去重

#include <bits/stdc++.h>
using namespace std;
#define int long long
using PII = pair<int, int>;

void ylh_() {
    const int N = 1e5;
    vector<int> pos(N + 1), next(N + 1, -1);
    auto trans = [&](string s) { //变换
        int res = 0;
        for (auto v : s) {
            res *= 10;
            res += (int)(v - '0');
        }
        return res;
    };
    auto ftrans = [&](int x) { //逆变换
        string r = "";
        while (x) {
            r += (char)((x % 10) + '0');
            x /= 10;
        }
        while (r.size() < 5) {
            r += '0';
        }
        reverse(r.begin(), r.end());
        return r;
    };
    string fst;
    int f, n;
    cin >> fst >> n;
    f = trans(fst);
    for (int i = 1, val; i <= n; ++i) {
        string s1, s2;
        cin >> s1 >> val >> s2;
        int j = trans(s1);
        if (s2 == "-1") { 
            next[j] = -1;
            pos[j] = val;
            continue;
        }
        int k = trans(s2);
        pos[j] = val;
        next[j] = k;
    }
    vector<int> vis(N + 1, 0);
    vector<int> ans1;
    vector<int> ans2;
    auto dfs = [&](auto&& dfs, int u) {
        if (vis[abs(pos[u])]) {
            ans2.push_back(u);
        }
        if (!vis[abs(pos[u])]) {
            ans1.push_back(u);
            vis[abs(pos[u])] = 1;
        }
        if (next[u] == -1) {
            return;
        }
        dfs(dfs, next[u]);
    };
    dfs(dfs, f);
    for (int i = 0; i < ans1.size(); ++i) {
        int u = ans1[i];
        if (i != ans1.size() - 1) {
            int v = ans1[i + 1];
            cout << ftrans(u) << ' ' << pos[u] << ' ' << ftrans(v) << '\n';
        } else {
            if (ans2.size()) {
                cout << ftrans(u) << ' ' << pos[u] << ' ' << -1 << '\n';
            } else {
                cout << ftrans(u) << ' ' << pos[u] << ' ' << -1;
            }
        }
    }
    for (int i = 0; i < ans2.size(); ++i) {
        int u = ans2[i];
        if (i != ans2.size() - 1) {
            int v = ans2[i + 1];
            cout << ftrans(u) << ' ' << pos[u] << ' ' << ftrans(v) << '\n';
        } else {
            cout << ftrans(u) << ' ' << pos[u] << ' ' << -1;
        }
    }
}

int32_t main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    int T = 1;
    // cin >> T;
    while (T--) {
        ylh_();
    }
    return 0;
}

L2-003 月饼

#include <bits/stdc++.h>
using namespace std;
#define int long long
using PII = pair<double, double>;

//坑点:月饼的两个参数是正数,并非正整数

void ylh_() {
    int n, D;
    cin >> n >> D;
    vector<PII> a(n + 1);
    for (int i = 1; i <= n; ++i) {
        cin >> a[i].second;
    }
    for (int i = 1; i <= n; ++i) {
        cin >> a[i].first;
    }
    sort(a.begin() + 1, a.end(), [&](PII x, PII y) {
        return x.first * y.second > y.first * x.second;
    });
    double ans = 0;
    for (int i = 1; i <= n; ++i) {
        if (D >= a[i].second) { //其实这里的比较是不合法的,最好使用eps,不过这样可以通过
            D -= a[i].second;
            ans += 1.00 * a[i].first;
        } else {
            ans += a[i].first * D / a[i].second;
            cout << fixed << setprecision(2) << ans << '\n';
            return;
        }
    }
    cout << fixed << setprecision(2) << ans << '\n';
}

int32_t main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    int T = 1;
    // cin >> T;
    while (T--) {
        ylh_();
    }
    return 0;
}

L2-004 这是二叉搜索树吗?

#include <bits/stdc++.h>
using namespace std;
#define int long long

void ylh_() {
    int n;
    cin >> n;
    vector<int> a(n + 1);
    for (int i = 1; i <= n; ++i) {
        cin >> a[i];
    }
    vector<int> l(n + 1), r(n + 1);
    int mxdep = 1;
    auto add = [&](auto&& add, int u, int p, int dep) -> void {
        mxdep = max(dep + 1, mxdep);
        if (a[p] < a[u]) {
            if (!l[u]) {
                l[u] = p;
            } else {
                add(add, l[u], p, dep + 1);
            }
        } else if (a[p] >= a[u]) {
            if (!r[u]) {
                r[u] = p;
            } else {
                add(add, r[u], p, dep + 1);
            }
        }
    };
    for (int i = 2; i <= n; ++i) {
        add(add, 1, i, 1);
    }
    vector<int> ans, pre;
    pre.push_back(0);
    auto dfs = [&](auto&& dfs, int u, int mode) -> void {
        pre.push_back(a[u]);
        if (mode == 1) {
            if (l[u])
                dfs(dfs, l[u], mode);
            if (r[u])
                dfs(dfs, r[u], mode);
        } else {
            if (r[u])
                dfs(dfs, r[u], mode);
            if (l[u])
                dfs(dfs, l[u], mode);
        }
        ans.push_back(a[u]);
    };
    dfs(dfs, 1, a[2] < a[1]);
    if (pre != a) {
        cout << "NO";
        return;
    }
    cout << "YES\n";
    for (int i = 0; i < ans.size(); ++i) {
        cout << ans[i];
        if (i != ans.size() - 1) {
            cout << ' ';
        }
    }
}

int32_t main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    int T = 1;
    // cin >> T;
    while (T--) {
        ylh_();
    }
    return 0;
}

L2-005 集合相似度

不记录写过的答案就只有21分,记了就25分过了,这可能不是正确做法?可能有更优。

#include <bits/stdc++.h>
using namespace std;
#define int long long
using PII = pair<int, int>;

void ylh_() {
    int n;
    cin >> n;
    vector<vector<int>> a(n + 1);
    for (int i = 1; i <= n; ++i) {
        int m;
        cin >> m;
        a[i].resize(m);
        for (int j = 0; j < m; ++j) {
            cin >> a[i][j];
        }
    }
    auto get = [&](int x, int y) -> PII {
        set<int> st1, st2, st3;
        for (auto v : a[x]) {
            st1.insert(v);
            st2.insert(v);
        }
        int res1, res2 = 0;
        for (auto v : a[y]) {
            st1.insert(v);
            if (st2.count(v) && !st3.count(v)) {
                ++res2;
                st3.insert(v);
            }
        }
        res1 = st1.size();
        return (PII) { res1, res2 };
    };
    int q;
    cin >> q;
    map<PII, double> mp;
    while (q--) {
        int x, y;
        cin >> x >> y;
        if (mp.count({ x, y })) {
            cout << fixed << setprecision(2) << mp[{ x, y }] << '%' << '\n';
            continue;
        }
        auto [d, u] = get(x, y);
        double ans = 100.00 * u / (double)d;
        mp[{ x, y }] = ans;
        cout << fixed << setprecision(2) << ans << '%' << '\n';
    }
}

int32_t main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    int T = 1;
    // cin >> T;
    while (T--) {
        ylh_();
    }
}

L2-006 树的遍历

网上有一些题解的建树是错误的,他们的左子节点和右子节点用的是乘二和乘二加一,这样子实际上会溢出,不过数据没有这种情况导致错误做法也能通过

#include <bits/stdc++.h>
using namespace std;
#define int long long
using PII = pair<int, int>;

void ylh_() {
    int n;
    cin >> n;
    vector<int> in(n), suf(n); // 中序和后序序列
    vector<int> ls(n, -1), rs(n, -1); // 左子节点和右子节点的索引
    vector<int> val(n); // 节点的值
    for (int i = 0; i < n; ++i) {
        cin >> suf[i];
    }
    for (int i = 0; i < n; ++i) {
        cin >> in[i];
    }
    int nodeCnt = 0;
    auto dfs = [&](auto&& dfs, int l1, int r1, int l2, int r2) -> int {
        // l1,r1: 中序遍历区间 [l1, r1]
        // l2,r2: 后序遍历区间 [l2, r2]
        // 返回当前子树的根节点索引
        if (l1 > r1 || l2 > r2) {
            return -1; // 空子树
        }
        // 创建新节点
        int u = nodeCnt++;
        val[u] = suf[r2]; // 后序遍历的最后一个节点是根
        // 在中序遍历中找到根的位置
        int t = l1;
        while (t <= r1 && in[t] != val[u]) {
            t++;
        }
        // 左子树的节点数
        int leftLen = t - l1;
        // 递归构建左右子树
        // 左子树:中序[l1, t-1],后序[l2, l2+leftLen-1]
        ls[u] = dfs(dfs, l1, t - 1, l2, l2 + leftLen - 1);
        // 右子树:中序[t+1, r1],后序[l2+leftLen, r2-1]
        rs[u] = dfs(dfs, t + 1, r1, l2 + leftLen, r2 - 1);
        return u;
    };
    int root = dfs(dfs, 0, n - 1, 0, n - 1);
    queue<int> q;
    q.push(root);
    vector<int> result;
    while (!q.empty()) {
        int u = q.front();
        q.pop();
        result.push_back(val[u]);
        if (ls[u] != -1)
            q.push(ls[u]);
        if (rs[u] != -1)
            q.push(rs[u]);
    }
    for (int i = 0; i < result.size(); i++) {
        if (i)
            cout << " ";
        cout << result[i];
    }
    cout << '\n';
}
int32_t main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    int T = 1;
    // cin >> T;
    while (T--) {
        ylh_();
    }
}

L2-007 家庭房产

坑点:编号可能存在0000,所以遍历的时候记得带0

#include <bits/stdc++.h>
using namespace std;
#define int long long
using PII = pair<int, int>;

void ylh_() {
    int n;
    cin >> n;
    const int N = 1e4;
    vector<int> vis(N + 10), p(N + 10), sz(N + 10);//这个编号是否有人,并查集父亲数组,并查集大小数组
    vector<int> cnt(N + 10), val(N + 10);//房屋数数组,房屋面积数组
    for (int i = 1; i <= N; ++i) {//初始化
        p[i] = i;
        sz[i] = 1;
    }
    auto find = [&](auto&& find, int u) -> int {//并查集合并
        return ((u == p[u]) ? p[u] : p[u] = find(find, p[u]));
    };
    auto merge = [&](int u, int v) -> void {//并查集按秩合并,同时合并两个权值:房屋数量和面积
        u = find(find, u);
        v = find(find, v);
        if (u == v)
            return;
        if (sz[u] >= sz[v]) {
            p[v] = u;
            sz[u] += sz[v];
            cnt[u] += cnt[v];
            val[u] += val[v];
        } else {
            p[u] = v;
            sz[v] += sz[u];
            cnt[v] += cnt[u];
            val[v] += val[u];
        }
        return;
    };
    vector<vector<int>> g(N + 1);//先存一下关系而不是直接合并的原因是因为cnt和val数组还没初始化完
    for (int i = 1; i <= n; ++i) {
        int idx, dad, mom;
        cin >> idx >> dad >> mom;
        vis[idx] = 1;
        if (dad != -1) {
            g[idx].push_back(dad);
        }
        if (mom != -1) {
            g[idx].push_back(mom);
        }
        int k;
        cin >> k;
        for (int j = 1; j <= k; ++j) {
            int kid;
            cin >> kid;
            g[idx].push_back(kid);
        }
        int t1, t2;
        cin >> t1 >> t2;
        cnt[idx] = t1;
        val[idx] = t2;
    }
    for (int i = 0; i <= N; ++i) { //开始合并
        if (vis[i] == 1) {
            for (auto v : g[i]) {
                vis[v] = 1;
                merge(v, i);
            }
        }
    }
    set<int> st;
    vector<int> minb(N + 10, -1), siz(N + 10, -1), ans1(N + 10, -1), ans2(N + 10, -1);//家庭最小编号,家庭成员数量,家庭房屋总数,家庭房屋总面积
    for (int i = 0; i <= N; ++i) {
        if (!vis[i])
            continue;
        int u = find(find, i);
        if (minb[u] == -1) {
            minb[u] = i;
        }
        minb[u] = min(i, minb[u]);
        siz[u] = sz[u];
        ans1[u] = cnt[u];
        ans2[u] = val[u];
    }
    vector<int> index;//找到所有家庭
    for (int i = 0; i <= N; ++i) {
        if (minb[i] != -1) {
            index.push_back(i);
        }
    }

    sort(index.begin(), index.end(), [&](int x, int y) {//按照房屋面积,编号排序
        if (ans2[x] * siz[y] == ans2[y] * siz[x]) {
            return minb[x] < minb[y];
        } else {
            return ans2[x] * siz[y] >= ans2[y] * siz[x];
        }
    });
    cout << index.size() << '\n';
    for (int i = 0; i < index.size(); ++i) {
        int u = index[i];
        if (minb[u] < 10) {
            cout << "000" << minb[u] << ' ';
        } else if (minb[u] < 100) {
            cout << "00" << minb[u] << ' ';
        } else if (minb[u] < 1000) {
            cout << "0" << minb[u] << ' ';
        } else {
            cout << minb[u] << ' ';
        }
        cout << siz[u] << ' ';
        double res1 = 1.0 * ans1[u] / (1.0 * siz[u]);
        double res2 = 1.0 * ans2[u] / (1.0 * siz[u]);
        cout << fixed << setprecision(3) << res1 << ' ' << res2;
        if (i != index.size() - 1) {
            cout << '\n';
        }
    }
}

int32_t main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    int T = 1;
    // cin >> T;
    while (T--) {
        ylh_();
    }
}

L2-008 最长对称子串

以为要写字符串哈希,但实际上暴力可以过
二分+字符串哈希的复杂度是$O(nlogn)$,马拉车是$O(n)$
这里我写个暴力好了,注意还有偶数长度回文串

#include <bits/stdc++.h>
using namespace std;
#define int long long
using PII = pair<int, int>;

void ylh_() {
    string s;
    getline(cin, s);
    int n = s.length();
    int ans = 1;
    for (int i = 0; i < n; ++i) {
        int l = i, r = i;
        while (l - 1 >= 0 && r + 1 < n && s[l - 1] == s[r + 1]) {
            --l;
            ++r;
        }
        ans = max(ans, r - l + 1);
    }
    for (int i = 0; i < n - 1; ++i) {
        int l = i, r = i + 1;
        if (s[i] != s[i + 1]) {
            continue;
        }
        while (l - 1 >= 0 && r + 1 < n && s[l - 1] == s[r + 1]) {
            --l;
            ++r;
        }
        ans = max(ans, r - l + 1);
    }
    cout << ans << '\n';
}

int32_t main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    int T = 1;
    // cin >> T;
    while (T--) {
        ylh_();
    }
}

L2-009 抢红包

模拟即可,注意排序还要根据抢红包的个数

#include <bits/stdc++.h>
using namespace std;
#define int long long
using PII = pair<int, int>;

void ylh_() {
    int n;
    cin >> n;
    vector<int> ans(n + 1), cnt(n + 1), id(n + 1);
    for (int i = 1; i <= n; ++i) {
        int m;
        cin >> m;
        id[i] = i;
        for (int j = 1; j <= m; ++j) {
            int idx, g;
            cin >> idx >> g;
            ans[idx] += g;
            ++cnt[idx];
            ans[i] -= g;
        }
    }
    sort(id.begin() + 1, id.end(), [&](int x, int y) {
        if (ans[x] == ans[y]) {
            if (cnt[x] == cnt[y]) {
                return x < y;
            } else {
                return cnt[x] > cnt[y];
            }
        }
        return ans[x] > ans[y];
    });
    for (int i = 1; i <= n; ++i) {
        double res = ans[id[i]] / 100.00;
        cout << id[i] << ' ' << fixed << setprecision(2) << res << '\n';
    }
}

int32_t main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    int T = 1;
    // cin >> T;
    while (T--) {
        ylh_();
    }
}

L2-010 排座位

并查集

#include <bits/stdc++.h>
using namespace std;
#define int long long
using PII = pair<int, int>;

void ylh_() {
    int n, m, k;
    cin >> n >> m >> k;
    vector<int> p(n + 1);
    for (int i = 1; i <= n; ++ i) {
        p[i] = i;
    }
    auto find = [&](auto &&find, int u) -> int{
        return u == p[u] ? u : p[u] = find(find, p[u]);
    };
    auto d = [&](int u, int v) -> void{
        u = find(find, u);
        v = find(find, v);
        if (u == v) return ;
        p[u] = v;
        return ;
    };
    vector<vector<int>> e(n + 1, vector<int>(n + 1, 0));
    for (int i = 1; i <= m; ++ i) {
        int u, v, w;
        cin >> u >> v >> w;
        if (w == 1) {
            d(u, v);
        } else {
            e[u][v] = e[v][u] = 1;
        }
    }
    for (int i = 1; i <= k; ++ i) {
        int u, v;
        cin >> u >> v;
        if (e[u][v]) {
            if (find(find, u) == find(find, v)) {
                cout << "OK but...\n";
            } else {
                cout << "No way\n";
            }
        } else {
            if (find(find, u) == find(find, v)) {
                cout << "No problem\n";
            } else {
                cout << "OK\n";
            }
        }
    }
}

int32_t main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    int T = 1;
    // cin >> T;
    while (T--) {
        ylh_();
    }
}

L2-011 玩转二叉树

你可以递归的真正去翻转一下,但是实际上只需要层序遍历的时候先右后左就行了

#include <bits/stdc++.h>
using namespace std;
#define int long long
using PII = pair<int, int>;

void ylh_() {
    int n;
    cin >> n;
    vector<int> in(n), pre(n);
    for (auto& i : in)
        cin >> i;
    for (auto& i : pre)
        cin >> i;
    vector<int> ls(n, -1), rs(n, -1), val(n);
    int cnt = 0;
    auto dfs = [&](auto&& dfs, int l1, int r1, int l2, int r2) -> int {
        if (l1 > r1)
            return -1;
        int u = cnt++;
        val[u] = pre[l2];

        int t = l1;
        while (t <= r1 && in[t] != val[u])
            t++;
        int left_len = t - l1;

        ls[u] = dfs(dfs, l1, t - 1, l2 + 1, l2 + left_len);
        rs[u] = dfs(dfs, t + 1, r1, l2 + left_len + 1, r2);

        return u;
    };
    int rt = dfs(dfs, 0, n - 1, 0, n - 1);
    queue<int> q;
    q.push(rt);
    vector<int> ans;
    while (!q.empty()) {
        int u = q.front();
        q.pop();
        ans.push_back(val[u]);
        if (rs[u] != -1)
            q.push(rs[u]);
        if (ls[u] != -1)
            q.push(ls[u]);
    }
    for (int i = 0; i < ans.size(); ++i) {
        cout << ans[i];
        if (i != ans.size() - 1)
            cout << ' ';
    }
}

int32_t main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    int T = 1;
    // cin >> T;
    while (T--) {
        ylh_();
    }
}

L2-012 关于堆的判断

#include <bits/stdc++.h>
using namespace std;
#define int long long
using PII = pair<int, int>;

void ylh_() {
    int n, q;
    cin >> n >> q;
    vector<int> a(n + 1);
    for (int i = 1; i <= n; ++i) cin >> a[i];

    vector<int> pq(n + 1);
    map<int, int> pos;
    int cnt = 1;
    auto insert = [&](int x) {
        int u = cnt++;
        pq[u] = x;
        pos[x] = u;
        while (u > 1 && pq[u / 2] > pq[u]) {
            swap(pq[u / 2], pq[u]);
            pos[pq[u / 2]] = u / 2;
            pos[pq[u]] = u;
            u /= 2;
        }
    };
    for (int i = 1; i <= n; ++i) insert(a[i]);
    while (q--) {//根据第二个单词排除操作二,根据第四个单词就可以判断是哪个操作了
        int x;
        string op;
        cin >> x >> op;
        if (op == "and") {
            int y;
            cin >> y;
            int px = pos[x], py = pos[y];
            bool sibling = (px / 2 == py / 2) && abs(px - py) == 1;
            cout << (sibling ? 'T' : 'F') << '\n';
            string dummy;
            cin >> dummy >> dummy;
        } else {
            string word;
            cin >> word;
            cin >> word;
            if (word == "root") {
                cout << (pos[x] == 1 ? 'T' : 'F') << '\n';
            } else if (word == "parent") {
                cin >> word;
                int y;
                cin >> y;
                bool parent = (pos[y] / 2 == pos[x]);
                cout << (parent ? 'T' : 'F') << '\n';
            } else {
                cin >> word;
                int y;
                cin >> y;
                bool child = (pos[x] / 2 == pos[y]);
                cout << (child ? 'T' : 'F') << '\n';
            }
        }
    }
}


int32_t main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    int T = 1;
    // cin >> T;
    while (T--) {
        ylh_();
    }
}

L2-013 红色警报

呃,怎么说呢,题目讲的可能不太清楚,大概就是说只要连通块数量增加,那么就要发出红色警报,所以我们每去掉一个点的时候重新再搜索一下不包含这个点的图的连通块数量就行,我这里用的是bfs

#include <bits/stdc++.h>
using namespace std;
#define int long long
using PII = pair<int, int>;

void ylh_() {
    int n, m;
    cin >> n >> m;
    vector<vector<int>> g(n);
    for (int i = 1; i <= m; ++i) {
        int u, v;
        cin >> u >> v;
        g[u].push_back(v);
        g[v].push_back(u);
    }
    vector<int> exist(n + 1, 1);
    auto bfs = [&]() -> int {
        vector<int> vis(n + 1);
        int cnt = 0;
        for (int i = 0; i < n; ++i) {
            if (vis[i] || !exist[i])
                continue;
            queue<int> q;
            q.push(i);
            ++cnt;
            while (!q.empty()) {
                auto u = q.front();
                q.pop();
                if (vis[u])
                    continue;
                vis[u] = 1;
                for (auto v : g[u]) {
                    if (!vis[v] && exist[v]) {
                        q.push(v);
                    }
                }
            }
        }
        return cnt;
    };
    int k;
    cin >> k;
    vector<int> res(k + 1);
    res[0] = bfs();
    for (int i = 1; i <= k; ++i) {
        int x;
        cin >> x;
        exist[x] = 0;
        res[i] = bfs();
        if (res[i] > res[i - 1]) {
            cout << "Red Alert: City " << x << " is lost!\n";
        } else {
            cout << "City " << x << " is lost.\n";
        }
        if (res[i] == 0) {
            cout << "Game Over.";
        }
    }
}

int32_t main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    int T = 1;
    // cin >> T;
    while (T--) {
        ylh_();
    }
}

L2-014 列车调度

用Set维护每一个轨道的尾巴,显然某个值比这个尾巴小的时候才能放进这个轨道,而且最好插入目前最相近的尾巴,如果不能插入,那么就新开一条轨道

#include <bits/stdc++.h>
using namespace std;
#define int long long
using PII = pair<int, int>;

void ylh_() {
    int n;
    cin >> n;
    set<int> st;
    st.insert(0);
    for(int i = 0; i < n; i++) {
        int t;
        cin >> t;
        auto it = st.upper_bound(t);
        if(it != st.end()) st.erase(it);
        st.insert(t);
    }
    cout << st.size() - 1 << endl;
}

int32_t main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    int T = 1;
    // cin >> T;
    while (T--) {
        ylh_();
    }
}

L2-015 互评成绩

时间复杂度可以用优先队列压一下,但是不压也能过,无所谓了

#include <bits/stdc++.h>
using namespace std;
#define int long long
using PII = pair<int, int>;

void ylh_() {
    int n, k, m;
    cin >> n >> k >> m;
    vector<int> a(n + 1);
    for (int i = 1; i <= n; ++i) {
        int x;
        cin >> x;
        int min_ = x, max_ = x, sum_ = x;
        for (int j = 1; j < k; ++j) {
            cin >> x;
            min_ = min(min_, x);
            max_ = max(max_, x);
            sum_ += x;
        }
        a[i] = sum_ - min_ - max_;
    }
    sort(a.begin() + 1, a.end(), greater<int>());
    for (int i = m; i >= 1; --i) {
        double res = 1.00 * a[i] / (k - 2);
        cout << fixed << setprecision(3) << res;
        if (i != 1) {
            cout << ' ';
        }
    }
}

int32_t main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    int T = 1;
    // cin >> T;
    while (T--) {
        ylh_();
    }
}

L2-016 愿天下有情人都是失散多年的兄妹

太保守了导致一开始少过几个点,注意即使为人父母也是可以被询问的
这个题具体来说就是我们可以直接往上搜四代,因为只有五代状态数不算多,复杂度可以接受

#include <bits/stdc++.h>
using namespace std;
#define int long long
using PII = pair<int, int>;

void ylh_() {
    int n;
    cin >> n;
    const int N = 1e5;
    vector<int> dad(N + 1, -1), mom(N + 1, -1), x(N + 1);
    for (int i = 1; i <= n; ++i) {
        int idx, f, m;
        char c;
        cin >> idx >> c >> f >> m;
        x[idx] = ((c == 'M') ? 1 : 2);
        dad[idx] = f;
        mom[idx] = m;
        if (f != -1) x[f] = 1;
        if (m != -1) x[m] = 2;//注意即使身为人父人母也是可以被询问的
    }
    int ok = 1;
    auto f = [&](auto&& f, int x, int y, int cnt) -> void {
        // cout << x << ' ' << y << '\n';
        if (x == -1 || y == -1) return ;
        if (x == y) {
            ok = 0;
            return;
        }
        if (cnt > 4)
            return;
        if (dad[x] != -1 && dad[y] != -1)
            f(f, dad[x], dad[y], cnt + 1);
        if (dad[x] != -1 && mom[y] != -1)
            f(f, dad[x], mom[y], cnt + 1);
        if (mom[x] != -1 && dad[y] != -1)
            f(f, mom[x], dad[y], cnt + 1);
        if (mom[x] != -1 && mom[y] != -1)
            f(f, mom[x], mom[y], cnt + 1);
    };
    int q;
    cin >> q;
    while (q--) {
        int u, v;
        cin >> u >> v;
        if (x[u] == x[v]) {
            cout << "Never Mind\n";
            continue;
        }
        ok = 1;
        f(f, u, v, 1);
        cout << ((ok) ? "Yes" : "No") << '\n';
    }
}

int32_t main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    int T = 1;
    // cin >> T;
    while (T--) {
        ylh_();
    }
}

L2-017 人以群分

偶数对半分最好,奇数的话外向多一个差就更大

#include <bits/stdc++.h>
using namespace std;
#define int long long
using PII = pair<int, int>;

void ylh_() {
    int n;
    cin >> n;
    vector<int> a(n + 1);
    for (int i = 1; i <= n; ++i) {
        cin >> a[i];
    }
    sort(a.begin() + 1, a.end());
    vector<int> pre(n + 1);
    for (int i = 1; i <= n; ++i) {
        pre[i] = pre[i - 1] + a[i];
    }
    int diff = pre[n] - 2 * pre[n / 2];
    cout << "Outgoing #: " << n / 2 + (n % 2 == 1) << '\n';
    cout << "Introverted #: " << n / 2 << '\n';
    cout << "Diff = " << diff;
}

int32_t main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    int T = 1;
    // cin >> T;
    while (T--) {
        ylh_();
    }
}

L2-018 多项式A除以B

比赛的时候拿不到满分就放弃吧,我已调试到疾苦

#include <bits/stdc++.h>
using namespace std;
#define int long long

const double eps = 1e-6;

void ylh_() {
    int n1;
    cin >> n1;
    vector<int> a1;
    vector<double> a2;
    for (int i = 1; i <= n1; ++i) {
        int x;
        double y;
        cin >> x >> y;
        a1.push_back(x);
        a2.push_back(y);
    }
    int n2;
    cin >> n2;
    vector<int> b1;
    vector<double> b2;
    for (int i = 1; i <= n2; ++i) {
        int x;
        double y;
        cin >> x >> y;
        b1.push_back(x);
        b2.push_back(y);
    }
    if (n1 == 0) {
        cout << "0 0 0.0\n 0 0 0.0";
        return;
    }
    
    // 被除式数组,下标为指数
    vector<double> a3(10010, 0.0);
    int max_a = 0;
    for (int i = 0; i < a1.size(); ++i) {
        a3[a1[i]] = a2[i];
        if (a1[i] > max_a) max_a = a1[i];
    }
    
    // 除式数组
    vector<double> b3(10010, 0.0);
    int max_b = 0;
    for (int i = 0; i < b1.size(); ++i) {
        b3[b1[i]] = b2[i];
        if (b1[i] > max_b) max_b = b1[i];
    }
    
    // 商数组
    vector<double> c3(10010, 0.0);
    int max_c = max_a - max_b;
    
    while (max_a >= max_b) {
        if (abs(a3[max_a]) < eps) {
            max_a--;
            continue;
        }
        double q = a3[max_a] / b3[max_b];
        c3[max_a - max_b] = q;
        
        // 更新被除式
        for (int i = max_a, j = max_b; i >= 0 && j >= 0; i--, j--) {
            a3[i] -= b3[j] * q;
        }
        
        while (max_a >= 0 && abs(a3[max_a]) < eps) {
            max_a--;
        }
    }
    
    auto print = [&](vector<double>& arr, int max_exp) {
        int cnt = 0;
        for (int i = 0; i <= max_exp; ++i) {
            if (abs(arr[i]) + 0.05 >= 0.1) cnt++;
        }
        cout << cnt;
        if (cnt == 0) {
            cout << " 0 0.0";
        } else {
            for (int i = max_exp; i >= 0; --i) {
                if (abs(arr[i]) + 0.05 >= 0.1) {
                    cout << ' ' << i << fixed << setprecision(1) << ' ' << arr[i];
                }
            }
        }
    };
    
    print(c3, max_c);
    cout << '\n';

    print(a3, max_a);
}

int32_t main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    int T = 1;
    // cin >> T;
    while (T--) {
        ylh_();
    }
    return 0;
}

L2-019 悄悄关注

#include <bits/stdc++.h>
using namespace std;
#define int long long
using PSI = pair<string, int>;

void ylh_() {
    int n;
    cin >> n;
    set<string> st;
    for (int i = 1; i <= n; ++i) {
        string s;
        cin >> s;
        st.insert(s);
    }
    int m;
    cin >> m;
    vector<PSI> a(m + 1);
    int sum = 0;
    for (int i = 1; i <= m; ++i) {
        cin >> a[i].first >> a[i].second;
        sum += a[i].second;
    }
    sort(a.begin() + 1, a.end(), [&](PSI x, PSI y) {
        return x.first < y.first;
    });
    vector<string> ans;
    for (int i = 1; i <= m; ++i) {
        if (a[i].second * m > sum) {
            if (!st.count(a[i].first)) {
                ans.push_back(a[i].first);
            }
        }
    }
    for (int i = 0; i < ans.size(); ++i) {
        cout << ans[i];
        if (i != ans.size() - 1) {
            cout << '\n';
        } else {
            return;
        }
    }
    cout << "Bing Mei You";
}

int32_t main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    int T = 1;
    // cin >> T;
    while (T--) {
        ylh_();
    }
}

L2-020 功夫传人

#include <bits/stdc++.h>
using namespace std;
#define int long long

void ylh_() {
    int n;
    double z, r;
    cin >> n >> z >> r;
    r /= 100;
    vector<vector<int>> g(n);
    vector<int> ddz(n + 1); // 得道者的倍数
    for (int i = 0; i < n; ++i) {
        int m;
        cin >> m;
        if (m == 0) {
            int k;
            cin >> k;
            ddz[i] = k;
        }
        for (int j = 1; j <= m; ++j) {
            int k;
            cin >> k;
            g[i].push_back(k);
        }
    }
    double ans = 0;
    auto dfs = [&](auto&& dfs, double cur, int u) {
        // cout << u << ' ' << cur << endl;
        if (ddz[u] > 0) {
            ans += cur * ddz[u];
            return;
        }
        double ncur = cur * (1.0 - r);
        for (auto v : g[u]) {
            dfs(dfs, ncur, v);
        }
    };
    dfs(dfs, z, 0);
    int ans_int = ans;
    cout << ans_int;
}

int32_t main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    int T = 1;
    // cin >> T;
    while (T--) {
        ylh_();
    }
}

L2-021 点赞狂魔

#include <bits/stdc++.h>
using namespace std;
#define int long long

void ylh_() {
    int n;
    cin >> n;
    vector<string> name(n + 1);
    vector<int> num(n + 1), idx(n + 1), k(n + 1);
    for (int i = 1; i <= n; ++i) {
        idx[i] = i;
        cin >> name[i] >> k[i];
        set<int> st;
        for (int j = 1; j <= k[i]; ++j) {
            int x;
            cin >> x;
            st.insert(x);
        }
        num[i] = st.size();
    }
    sort(idx.begin() + 1, idx.end(), [&](int x, int y) {
        if (num[x] == num[y])
            return num[x] * k[y] > num[y] * k[x];
        return num[x] > num[y];
    });
    if (n == 1) {
        cout << name[idx[1]] << " - -";
    } else if (n == 2) {
        cout << name[idx[1]] << ' ' << name[idx[2]] << " -";
    } else {
        cout << name[idx[1]] << ' ' << name[idx[2]] << ' ' << name[idx[3]];
    }
}

int32_t main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    int T = 1;
    // cin >> T;
    while (T--) {
        ylh_();
    }
}

L2-022 重排链表

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1e5 + 5;

void ylh_() {
    int st, n;
    cin >> st >> n;
    vector<int> data(N, 0), nxt(N, -1);
    
    for (int i = 1; i <= n; ++i) {
        int addr, val, next;
        cin >> addr >> val >> next;
        data[addr] = val;
        nxt[addr] = next;
    }
    
    vector<int> list;
    int cur = st;
    while (cur != -1) {
        list.push_back(cur);
        cur = nxt[cur];
    }
    int l = 0, r = list.size() - 1;
    vector<int> res;
    while (l <= r) {
        if (l == r) {
            res.push_back(list[l]);
            break;
        }
        res.push_back(list[r]);
        res.push_back(list[l]);
        l++;
        r--;
    }
    for (int i = 0; i < res.size(); ++i) {
        cout << setw(5) << setfill('0') << res[i] << " " << data[res[i]] << " ";
        if (i == res.size() - 1) cout << "-1\n";
        else cout << setw(5) << setfill('0') << res[i + 1] << "\n";
    }
}

int32_t main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    int T = 1;
    // cin >> T;
    while (T--) {
        ylh_();
    }
    return 0;
}

L2-023 图着色问题

数据规模小随便弄下就能过,但是要注意颜色数是等于K而不是小于等于

#include <bits/stdc++.h>
using namespace std;
#define int long long
using PII = pair<int, int>;

void ylh_() {
    int n, m, k;
    cin >> n >> m >> k;
    vector<vector<int>> g(n + 1);
    for (int i = 1; i <= m; ++i) {
        int x, y;
        cin >> x >> y;
        g[x].push_back(y);
        g[y].push_back(x);
    }
    int q;
    cin >> q;
    vector<int> a(n + 1);
    set<int> st;
    while (q--) {
        for (int i = 1; i <= n; ++i) {
            cin >> a[i];
            st.insert(a[i]);
        }
        bool f = 1;
        for (int i = 1; i <= n; ++i) {
            for (auto v : g[i]) {
                if (a[i] == a[v]) {
                    f = 0;
                }
            }
        }
        if (f && st.size() == k) {
            cout << "Yes\n";
        } else {
            cout << "No\n";
        }
        st.clear();
    }
}

int32_t main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    int T = 1;
    // cin >> T;
    while (T--) {
        ylh_();
    }
}

L2-024 部落

刷到这里天梯赛L2好多并查集板子。。。还是要会这个

#include <bits/stdc++.h>
using namespace std;
#define int long long

void ylh_() {
    int n;
    cin >> n;
    vector<int> a(n + 1);
    const int N = 1e4;
    vector<int> p(N + 1);
    iota(p.begin(), p.end(), 0);
    auto findx = [&](auto&& findx, int x) -> int {
        return x == p[x] ? x : p[x] = findx(findx, p[x]);
    };
    auto find = [&](int x) -> int {
        return findx(findx, x);
    };
    int cnt = 0;
    auto merge = [&](int u, int v) -> void {
        u = find(u), v = find(v);
        if (u == v)
            return;
        ++cnt;
        p[u] = v;
    };
    set<int> st;
    for (int i = 1; i <= n; ++i) {
        int k, p1;
        cin >> k >> p1;
        int pi;
        st.insert(p1);
        for (int i = 2; i <= k; ++i) {
            cin >> pi;
            merge(pi, p1);
            st.insert(pi);
        }
    }

    int q;
    cin >> q;
    cout << st.size() << ' ' << st.size() - cnt << '\n';
    while (q--) {
        int x, y;
        cin >> x >> y;
        cout << ((find(x) == find(y)) ? 'Y' : 'N') << '\n';
    }
}

int32_t main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    int T = 1;
    // cin >> T;
    while (T--) {
        ylh_();
    }
}

L2-025 分而治之

记录度数就行,度数为0就孤立了

#include <bits/stdc++.h>
using namespace std;
#define int long long

void ylh_() {
    int n, m;
    cin >> n >> m;
    vector<vector<int>> g(n + 1);
    vector<int> d(n + 1);
    for (int i = 1; i <= m; ++i) {
        int u, v;
        cin >> u >> v;
        g[u].push_back(v);
        g[v].push_back(u);
        ++d[u];
        ++d[v];
    }
    int q;
    cin >> q;
    while (q--) {
        int t;
        cin >> t;
        vector<int> des(n + 1, 0);
        vector<int> deg = d;
        for (int i = 1; i <= t; ++i) {
            int u;
            cin >> u;
            des[u] = 1;
            for (auto v : g[u]) {
                --deg[v];
            }
        }
        int f = 1;
        for (int i = 1; i <= n; ++i) {
            if (!des[i]) {
                if (deg[i] > 0) {
                    f = 0;
                }
            }
        }
        if (f) {
            cout << "YES\n";
        } else {
            cout << "NO\n";
        }
    }
}

int32_t main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    int T = 1;
    // cin >> T;
    while (T--) {
        ylh_();
    }
}

L2-026 小字辈

是不是bfs好一点,我这里用的dfs,无所谓了

#include <bits/stdc++.h>
using namespace std;
#define int long long

void ylh_() {
    int n;
    cin >> n;
    vector<vector<int>> g(n + 1);
    int rt = 0;
    for (int i = 1; i <= n; ++i) {
        int f;
        cin >> f;
        if (f == -1) {
            rt = i;
            continue;
        }
        g[f].push_back(i);
    }
    int mxdep = 1;
    vector<int> ans;
    auto dfs = [&](auto&& dfs, int u, int dep) -> void {
        if (dep == mxdep) {
            ans.push_back(u);
        }
        if (dep > mxdep) {
            ans.clear();
            mxdep = dep;
            ans.push_back(u);
        }
        for (auto v : g[u]) {
            dfs(dfs, v, dep + 1);
        }
    };
    dfs(dfs, rt, 1);
    sort(ans.begin(), ans.end());
    cout << mxdep << '\n';
    for (int i = 0; i < ans.size(); ++i) {
        cout << ans[i];
        if (i != ans.size() - 1) {
            cout << ' ';
        }
    }
}

int32_t main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    int T = 1;
    // cin >> T;
    while (T--) {
        ylh_();
    }
}

L2-027 名人堂与代金券

排个序输出就行了

#include <bits/stdc++.h>
using namespace std;
#define int long long

void ylh_() {
    int n, g, k;
    cin >> n >> g >> k;
    vector<pair<string, int>> a(n + 1);
    int ans = 0;
    for (int i = 1; i <= n; ++i) {
        cin >> a[i].first >> a[i].second;
        if (a[i].second >= g) {
            ans += 50;
        } else if (a[i].second >= 60) {
            ans += 20;
        }
    }
    cout << ans << '\n';
    sort(a.begin() + 1, a.end(), [&](pair<string, int> x, pair<string, int> y) {
        if (x.second == y.second)
            return x.first < y.first;
        return x.second > y.second;
    });
    int rank = 1;
    a[0] = { "fkxqsvivo50", a[1].second };
    for (int i = 1; i <= n; ++i) {
        if (a[i].second != a[i - 1].second) {
            rank = i;
        }
        if (rank > k)
            break;
        cout << rank << ' ' << a[i].first << ' ' << a[i].second << '\n';
    }
}

int32_t main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    int T = 1;
    // cin >> T;
    while (T--) {
        ylh_();
    }
}

L2-028 秀恩爱分得快

写完发现有点啰嗦,但是能过就行

#include <bits/stdc++.h>
using namespace std;
#define int long long

const double EPS = 1e-5;

void ylh_() {
    int n, k;
    cin >> n >> k;
    vector<int> sex(n + 1);
    vector<vector<int>> p(k + 1);
    for (int i = 1; i <= k; ++i) {
        int m;
        cin >> m;
        p[i].resize(m + 1);
        p[i][0] = m;
        for (int j = 1; j <= m; ++j) {
            string s;
            cin >> s;
            int num = 0;
            if (s[0] == '-') {
                for (int l = 1; l < s.length(); ++l) {
                    num *= 10;
                    num += s[l] - '0';
                }
                sex[num] = 0;
            } else {
                for (int l = 0; l < s.length(); ++l) {
                    num *= 10;
                    num += s[l] - '0';
                }
                sex[num] = 1;
            }
            p[i][j] = num;
        }
    }
    int x, y;
    cin >> x >> y;
    x = abs(x), y = abs(y);
    vector<double> px(n);
    vector<double> py(n);
    double max_x = 0, max_y = 0;
    for (int i = 1; i <= k; ++i) {
        int pos = -1;
        for (int j = 1; j <= p[i][0]; ++j) {
            if (p[i][j] == x) {
                pos = j;
            }
        }
        if (pos == -1) {
            continue;
        }
        for (int j = 1; j <= p[i][0]; ++j) {
            int v = p[i][j];
            if (sex[v] == sex[x])
                continue;
            px[v] += 1.0 / p[i][0];
            max_x = max(px[v], max_x);
        }
    }

    for (int i = 1; i <= k; ++i) {
        int pos = -1;
        for (int j = 1; j <= p[i][0]; ++j) {
            if (p[i][j] == y) {
                pos = j;
            }
        }
        if (pos == -1) {
            continue;
        }
        for (int j = 1; j <= p[i][0]; ++j) {
            int v = p[i][j];
            if (sex[v] == sex[y])
                continue;
            py[v] += 1.0 / p[i][0];
            max_y = max(py[v], max_y);
        }
    }

    auto equal = [](double x, double y) -> bool {
        return (abs(x - y) <= EPS);
    };
    auto print = [&](int x) -> void {
        if (sex[x] == 0) {
            cout << '-' << x;
        } else {
            cout << x;
        }
    };
    if (equal(max_x, px[y]) && equal(max_y, py[x])) {
        print(x);
        cout << ' ';
        print(y);
        return;
    }

    vector<int> ansx, ansy;
    for (int i = 0; i < n; ++i) {
        if (sex[x] != sex[i] && equal(max_x, px[i])) {
            ansx.push_back(i);
        }
    }
    for (int i = 0; i < n; ++i) {
        if (sex[y] != sex[i] && equal(max_y, py[i])) {
            ansy.push_back(i);
        }
    }
    for (int i = 0; i < ansx.size(); ++i) {
        print(x);
        cout << ' ';
        print(ansx[i]);
        cout << '\n';
    }

    for (int i = 0; i < ansy.size(); ++i) {
        print(y);
        cout << ' ';
        print(ansy[i]);
        cout << '\n';
    }
}

int32_t main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    int T = 1;
    // cin >> T;
    while (T--) {
        ylh_();
    }
}

L2-029 特立独行的幸福

没见过这么读起来这么难受的题面

遍历每个数的时候,对每个数操作,如果路径里有的答案就不要了(因为显然这个数是个依附别的数的数),然后注意一下当前这个数要不是依附别的数的数才能算进答案里

#include <bits/stdc++.h>
using namespace std;
#define int long long

int isp(int x) {
    if (x == 1)
        return 1;
    for (int i = 2; i * i <= x; ++i) {
        if (x % i == 0)
            return 1;
    }
    return 2;
}

void ylh_() {
    int l, r;
    cin >> l >> r;
    map<int, int> mp;
    set<int> ex;
    for (int i = l; i <= r; ++i) {
        int cur = i;
        int cnt = 0;
        set<int> st;
        st.insert(cur);
        while (1) {
            int sum = 0;
            while (cur) {
                sum += (cur % 10) * (cur % 10);
                cur /= 10;
            }
            cur = sum;
            if (mp.count(cur)) {
                mp.erase(cur);
            }
            if (cur == 1)
                break;
            if (st.count(cur))
                break;
            st.insert(cur);
            ex.insert(cur);
        }
        if (cur == 1 && !ex.count(i)) {
            mp[i] = st.size() * (isp(i));
            ex.insert(i);
        }
    }
    if (mp.size() == 0) {
        cout << "SAD";
        return;
    }
    for (auto [a, b] : mp) {
        cout << a << ' ' << b << '\n';
    }
}

int32_t main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    int T = 1;
    // cin >> T;
    while (T--) {
        ylh_();
    }
}

L2-030 冰岛人

注意一种情况就是,可能两个人的公共祖先存在,但是只在一个人的五代以内
因为没给数据范围写了一发暴力发现可以过

#include <bits/stdc++.h>
using namespace std;
#define int long long
using PII = pair<int, int>;

void ylh_() {
    int n;
    cin >> n;
    map<string, int> sex;
    map<string, string> fa;
    for (int i = 1; i <= n; ++i) {
        string x, y;
        cin >> x >> y;
        char ed = *(y.end() - 1);
        if (ed == 'm') {
            sex[x] = 1;
            fa[x] = "-1";
        } else if (ed == 'f') {
            sex[x] = 0;
            fa[x] = "-1";
        } else if (ed == 'n') {
            sex[x] = 1;
            for (int j = 1; j <= 4; ++j)
                y.pop_back();
            fa[x] = y;
        } else {
            sex[x] = 0;
            for (int j = 1; j <= 7; ++j) {
                y.pop_back();
            }
            fa[x] = y;
        }
    }
    auto check = [&](string x, string y) -> bool {
        vector<string> fx, fy;
        string cur = x;
        fx.push_back(x);
        for (int i = 0; i < 3; i++) {
            if (fa[cur] != "-1") {
                cur = fa[cur];
                fx.push_back(cur);
            } else {
                break;
            }
        }
        cur = y;
        fy.push_back(y);
        for (int i = 0; i < 3; i++) {
            if (fa[cur] != "-1") {
                cur = fa[cur];
                fy.push_back(cur);
            } else {
                break;
            }
        }
        for (auto s1 : fx) {
            for (string j = y; j != "-1"; j = fa[j]) {
                if (s1 == j) {
                    return false;
                }
            }
        }
        for (auto s2 : fy) {
            for (string j = x; j != "-1"; j = fa[j]) {
                if (s2 == j) {
                    return false;
                }
            }
        }
        return true;
    };
    int q;
    cin >> q;
    while (q--) {
        string x, y, z;
        cin >> x >> z >> y >> z;
        if (!sex.count(x) || !sex.count(y)) {
            cout << "NA\n";
            continue;
        }
        if (sex[x] == sex[y]) {
            cout << "Whatever\n";
            continue;
        }
        if (check(x, y)) {
            cout << "Yes\n";
        } else {
            cout << "No\n";
        }
    }
}

int32_t main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    int T = 1;
    // cin >> T;
    while (T--) {
        ylh_();
    }
}

L2-031 深入虎穴

注意一号点不是入口,找到入口的方式就是找到入度为0的点就行了

#include <bits/stdc++.h>
using namespace std;
#define int long long
using PII = pair<int, int>;

void ylh_() {
    int n;
    cin >> n;
    int st = 0;
    vector<int> d(n + 1);
    vector<vector<int>> g(n + 1);
    for (int i = 1; i <= n; ++i) {
        int m;
        cin >> m;
        for (int j = 1; j <= m; ++j) {
            int v;
            cin >> v;
            g[i].push_back(v);
            ++d[v];
        }
    }
    for (int i = 1; i <= n; ++i) {
        if (d[i] == 0) {
            st = i;
        }
    }
    int ans = 1;
    int mxdep = 1;
    auto dfs = [&](auto&& dfs, int u, int dep) -> void {
        if (dep > mxdep) {
            mxdep = dep;
            ans = u;
        }
        for (auto v : g[u]) {
            dfs(dfs, v, dep + 1);
        }
    };
    dfs(dfs, st, 1);
    cout << ans;
}

int32_t main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    int T = 1;
    // cin >> T;
    while (T--) {
        ylh_();
    }
}

L2-032 彩虹瓶

用个栈表示货架就行了

#include <bits/stdc++.h>
using namespace std;
#define int long long
using PII = pair<int, int>;

void ylh_() {
    int n, m, k;
    cin >> n >> m >> k;
    stack<int> st;
    for (int i = 1; i <= k; ++ i) {
        bool ok = 1;
        int cur = 1;
        for (int j = 1; j <= n; ++ j) {
            int x;
            cin >> x;
            if (x == cur) {
                ++ cur;
                while (!st.empty() && st.top() == cur) {
                    ++ cur;
                    st.pop();
                }
            } else {
                if (st.size() < m) {
                    st.push(x);
                } else {
                    ok = 0;
                }
            }
        }
        if (st.size()) {
            ok = 0;
        }
        if (ok) {
            cout << "YES\n";
        } else {
            cout << "NO\n";
        }
        while (st.size()) st.pop();
    }
}

int32_t main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    int T = 1;
    // cin >> T;
    while (T--) {
        ylh_();
    }
}

L2-033 简单计算器

按题意模拟即可

#include <bits/stdc++.h>
using namespace std;
#define int long long

void ylh_() {
    int n;
    cin >> n;
    stack<int> num;
    stack<char> f;
    for (int i = 1; i <= n; ++i) {
        int x;
        cin >> x;
        num.push(x);
    }
    for (int i = 1; i < n; ++i) {
        char c;
        cin >> c;
        f.push(c);
    }
    while (num.size() >= 2) {
        int y = num.top();
        num.pop();
        int x = num.top();
        num.pop();
        char op = f.top();
        f.pop();
        if (op == '+') {
            num.push(x + y);
        } else if (op == '-') {
            num.push(x - y);
        } else if (op == '*') {
            num.push(x * y);
        } else {
            if (y == 0) {
                cout << "ERROR: " << x << '/' << 0;
                return;
            } else {
                num.push(x / y);
            }
        }
    }
    cout << num.top() << '\n';
}

int32_t main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    int T = 1;
    // cin >> T;
    while (T--) {
        ylh_();
    }
}

L2-034 口罩发放

有点小细节的模拟
注意第一类答案的排序和第二类的答案的排序是不同的
然后身份证必须是18位数字,其他字符不行
然后可能一个人刚开始上报的状态是0,后面是1

#include <bits/stdc++.h>
using namespace std;
#define int long long

struct apl {
    string name, id; // 名字,身份证
    int state, time, sx; // 状态,提交时间,出现顺序
}; // 申请

void ylh_() {
    int d, p;
    cin >> d >> p;
    map<string, int> lst; // 身份证号上次申请到口罩的天数
    map<string, string> Name; // 身份证号对应名字
    map<string, int> ok; // 是否被记入答案2
    vector<string> ans1, ans2; // 答案1和答案2
    for (int i = 1; i <= d; ++i) {
        int t, s;
        cin >> t >> s;
        vector<apl> a; // 既然时间无序我们就让他有序,输入进来再排序
        for (int j = 1; j <= t; ++j) {
            string s1, s2, s3, s4;
            cin >> s1 >> s2 >> s3 >> s4;
            if (s2.length() != 18)
                continue;
            int all_num = 1;
            for (auto v : s2) {
                if (v < '0' || v > '9')
                    all_num = 0;
            }
            if (!all_num)
                continue;
            int st = (s3 == "1");
            int times = ((s4[0] - '0') * 10 + s4[1] - '0') * 60 + ((s4[3] - '0') * 10 + s4[4] - '0');
            a.push_back({ s1, s2, st, times, j });
            if (st && !ok.count(s2)) {
                ans2.push_back(s2);
                ok[s2] = 1;
            }
            Name[s2] = s1;
        }
        sort(a.begin(), a.end(), [&](apl x, apl y) {
            if (x.time == y.time)
                return x.sx < y.sx;
            else
                return x.time < y.time;
        });
        for (auto [name, id, st, __, _] : a) {
            if ((!lst.count(id) || i - lst[id] > p) && s > 0) {
                ans1.push_back(id);
                --s;
                lst[id] = i;
            }
        }
    }
    for (auto s : ans1) {
        cout << Name[s] << ' ' << s << '\n';
    }
    for (auto s : ans2) {
        cout << Name[s] << ' ' << s << '\n';
    }
}

int32_t main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    int T = 1;
    // cin >> T;
    while (T--) {
        ylh_();
    }
}

L2-035 完全二叉树的层序遍历

直接拿后序遍历的顺序填数字就行

#include <bits/stdc++.h>
using namespace std;
#define int long long

void ylh_() {
    int n;
    cin >> n;
    vector<int> res(1, 0);
    auto dfs = [&](auto&& dfs, int u) -> void {
        if (2 * u <= n) {
            dfs(dfs, 2 * u);
        }
        if (2 * u + 1 <= n) {
            dfs(dfs, 2 * u + 1);
        }
        res.push_back(u);
    };
    dfs(dfs, 1);
    vector<int> a(n + 1);
    for (int i = 1; i <= n; ++i) {
        int x;
        cin >> x;
        a[res[i]] = x;
    }
    for (int i = 1; i <= n; ++i) {
        cout << a[i];
        if (i != n) {
            cout << ' ';
        }
    }
}

int32_t main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    int T = 1;
    // cin >> T;
    while (T--) {
        ylh_();
    }
}

L2-036 网红点打卡攻略

有几个注意点
1.要出门,也要回家,要看回家和出门存不存在路径
2.cnt是可行的路径,而不是最优路径(我这里写错一发)

#include <bits/stdc++.h>
using namespace std;
#define int long long
using PII = pair<int, int>;

void ylh_() {
    int n, m, k;
    cin >> n >> m;
    vector<map<int, int>> g(n + 1);
    for (int i = 1; i <= m; ++i) {
        int u, v, w;
        cin >> u >> v >> w;
        g[u][v] = w;
        g[v][u] = w;
    }
    cin >> k;
    const int INF = 2e18;
    int ans = -1;
    int cnt = 0;
    int Min = INF;

    for (int i = 1, c; i <= k; ++i) {
        cin >> c;
        vector<int> a(c + 2, 0);
        set<int> st;
        for (int j = 1; j <= c; ++j) {
            cin >> a[j];
            st.insert(a[j]);
        }
        if (st.size() != n || c != n) {
            continue;
        }
        int ok = 1;
        int res = 0;
        for (int j = 1; j <= c + 1; ++j) {
            if (!ok || !g[a[j - 1]].count(a[j])) {
                ok = 0;
                continue;
            }
            res += g[a[j - 1]][a[j]];
        }
        if (!ok)
            continue;
        ++cnt;
        if (res < Min) {
            ans = i;
            Min = res;
        }
    }
    cout << cnt << '\n'
         << ans << ' ' << Min;
}

int32_t main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    int T = 1;
    // cin >> T;
    while (T--) {
        ylh_();
    }
}

L2-037 包装机

挺好的小模拟

#include <bits/stdc++.h>
using namespace std;
#define int long long
using PII = pair<int, int>;

void ylh_() {
    int n, m, s;
    cin >> n >> m >> s;
    stack<char> st;
    vector<queue<char>> q(n + 1); // 其实用队列,栈,数组啥的都行,感觉队列好模拟一点
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= m; ++j) {
            char c;
            cin >> c;
            q[i].push(c);
        }
    }
    vector<char> ans;
    auto op0 = [&]() -> void {
        if (st.empty()) {
            return;
        }
        ans.push_back(st.top());
        st.pop();
    };
    auto op = [&](int x) -> void {
        if (q[x].size() == 0) {
            return;
        }
        if (st.size() == s) {
            op0();
        }
        st.push(q[x].front());
        q[x].pop();
    };
    int x;
    while (cin >> x) {
        if (x == -1) {
            for (int i = 0; i < ans.size(); ++i) {
                cout << ans[i];
            }
            return;
        } else {
            (x == 0) ? op0() : op(x);
        }
    }
}

int32_t main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    int T = 1;
    // cin >> T;
    while (T--) {
        ylh_();
    }
}

L2-038 病毒溯源

bfs或者dfs都可以,我这里用的dfs
一个是要知道怎么记录路径(dfs回溯,基础知识)
另外就是要知道怎么获取字典序最小(给每个点的边排序就可以控制遍历顺序)

#include <bits/stdc++.h>
using namespace std;
#define int long long

using PII = pair<int, int>;
const int INF = 2e18;

void ylh_() {
    int n;
    cin >> n;
    vector<vector<int>> g(n);
    for (int i = 0; i < n; ++i) {
        int k;
        cin >> k;
        for (int j = 1; j <= k; ++j) {
            int x;
            cin >> x;
            g[i].push_back(x);
        }
        sort(g[i].begin(), g[i].end());
    }
    vector<int> res, ans;
    int Max = 0;
    auto dfs = [&](auto&& dfs, int u) -> void {
        if (res.size() > Max) {
            Max = res.size();
            ans = res;
        }
        for (auto v : g[u]) {
            res.push_back(v);
            dfs(dfs, v);
            res.pop_back();
        }
    };
    for (int i = 0; i < n; ++i) {
        res.clear();
        res.push_back(i);
        dfs(dfs, i);
    }
    cout << ans.size() << '\n';
    for (int i = 0; i < ans.size(); ++i) {
        cout << ans[i];
        if (i < ans.size() - 1) {
            cout << ' ';
        }
    }
}

int32_t main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    int T = 1;
    // cin >> T;
    while (T--) {
        ylh_();
    }
}

L2-039 清点代码库

STL瞎写一下就行,之所以放负的cnt是因为set本来是顺序嘛,负数倒一倒就行了

#include <bits/stdc++.h>
using namespace std;
#define int long long

using PII = pair<int, int>;
const int INF = 2e18;

void ylh_() {
    int n, m;
    cin >> n >> m;
    map<vector<int>, int> mp;
    for (int i = 1; i <= n; ++i) {
        vector<int> a(m);
        for (int j = 0; j < m; ++j) {
            cin >> a[j];
        }
        mp[a]++;
    }
    set<pair<int, vector<int>>> ans;
    for (auto [vec, cnt] : mp) {
        ans.insert({ -cnt, vec });
    }
    cout << ans.size() << '\n';
    for (auto [cnt, vec] : ans) {
        cout << -cnt << ' ';
        for (int i = 0; i < m; ++i) {
            cout << vec[i] << " \n"[i == m - 1];
        }
    }
}

int32_t main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    int T = 1;
    // cin >> T;
    while (T--) {
        ylh_();
    }
}

L2-040 哲哲打游戏

依照题意模拟即可

#include <bits/stdc++.h>
using namespace std;
#define int long long

using PII = pair<int, int>;
using AIT = array<int, 3>;

void ylh_() {
    int n, m;
    cin >> n >> m;
    vector<vector<int>> a(n + 1);
    for (int i = 1; i <= n; ++i) {
        int k;
        cin >> k;
        a[i].resize(k + 1);
        a[i][0] = k;
        for (int j = 1; j <= k; ++j) {
            cin >> a[i][j];
        }
    }
    vector<int> cd(101); // 存档
    int pos = 1;
    for (int i = 1; i <= m; ++i) {
        int op, x;
        cin >> op >> x;
        if (op == 1) {
            cd[x] = pos;
            cout << pos << '\n';
        } else if (op == 2) {
            pos = cd[x];
        } else {
            pos = a[pos][x];
        }
    }
    cout << pos;
}

int32_t main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    int T = 1;
    // cin >> T;
    while (T--) {
        ylh_();
    }
}

L2-041 插松枝

模拟,感觉有点难分析,需要仔细读题分析

#include <bits/stdc++.h>
using namespace std;
#define int long long

using PII = pair<int, int>;
using AIT = array<int, 3>;

// 首先弄清楚,他优先是在小盒子里拿的,然后才会去推送器拿
// 一根插完只有两种可能,第一种就是没得拿了,第二种就是拿不到了

void ylh_() {
    int n, m, k;
    cin >> n >> m >> k;
    vector<int> a(n + 1);
    for (int i = 1; i <= n; ++i) {
        cin >> a[i];
    }
    queue<int> q; // 推送器
    stack<int> st; // 盒子
    vector<int> res; // 手上的松枝
    vector<vector<int>> ans; // 答案
    for (int i = 1; i <= n; ++i) {
        q.push(a[i]);
    }
    auto get = [&]() -> bool {
        if (res.size() == 0) {
            if (!st.empty()) {
                res.push_back(st.top());
                st.pop();
                return 1;
            }
            if (!q.empty()) {
                res.push_back(q.front());
                q.pop();
                return 1;
            }
        } else {
            if (!st.empty() && st.top() <= res.back()) {
                res.push_back(st.top());
                st.pop();
                return 1;
            }
            while (!q.empty() && q.front() > res.back() && st.size() < m) {
                st.push(q.front());
                q.pop();
            }
            if (!q.empty() && q.front() <= res.back()) {
                res.push_back(q.front());
                q.pop();
                return 1;
            }
        }
        return 0;
    };
    while (q.size() + st.size() > 0) {
        int f = get();
        // for (auto v : res) {
        //     cout << v << ' ';
        // }
        // cout << endl
        //      << f << endl;
        if (!f || res.size() == k) {
            ans.push_back(res);
            res.clear();
        }
    }
    if (res.size() != 0) {
        ans.push_back(res);
    }
    for (auto vec : ans) {
        for (int i = 0; i < vec.size(); ++i) {
            cout << vec[i] << " \n"[i == vec.size() - 1];
        }
    }
}

int32_t main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    int T = 1;
    // cin >> T;
    while (T--) {
        ylh_();
    }
}

L2-042 老板的作息表

#include <bits/stdc++.h>
using namespace std;
#define int long long

using PII = pair<int, int>;

void ylh_() {
    auto trans_to = [&](string s) {
        int times = ((s[0] - '0') * 10 + (s[1] - '0')) * 3600 + ((s[3] - '0') * 10 + (s[4] - '0')) * 60 + ((s[6] - '0') * 10 + (s[7] - '0'));
        return times;
    };
    auto trans_back = [&](int x) {
        string s_hour, s_min, s_s;
        int hour = x / 3600, min = x / 60 % 60, s = x % 60;
        s_hour = ((hour < 10) ? "0" + to_string(hour) : to_string(hour));
        s_min = ((min < 10) ? "0" + to_string(min) : to_string(min));
        s_s = ((s < 10) ? "0" + to_string(s) : to_string(s));
        string res = s_hour + ":" + s_min + ":" + s_s;
        return res;
    };
    int n;
    cin >> n;
    vector<PII> a(n + 1);
    for (int i = 1; i <= n; ++i) {
        string s1, s2;
        cin >> s1 >> s2 >> s2;
        a[i] = { trans_to(s1), trans_to(s2) };
    }
    sort(a.begin() + 1, a.end());
    auto print = [&](int t1, int t2) -> void {
        cout << trans_back(t1) << " - " << trans_back(t2) << '\n';
    };
    if (a[1].first != 0) {
        print(0ll, a[1].first);
    }
    for (int i = 2; i <= n; ++i) {
        if (a[i].first != a[i - 1].second) {
            print(a[i - 1].second, a[i].first);
        }
    }
    const int ED = 23 * 3600 + 59 * 60 + 59;
    if (a[n].second != ED) {
        print(a[n].second, ED);
    }
}

int32_t main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    int T = 1;
    // cin >> T;
    while (T--) {
        ylh_();
    }
}

L2-043 龙龙送外卖

怎么说呢,所有点到起点的经过边数都要走两遍,但是没说要回外卖站,所以减掉一个最深点的深度就行

#include <bits/stdc++.h>
using namespace std;
#define int long long

using PII = pair<int, int>;

void ylh_() {
    int n, m;
    cin >> n >> m;
    vector<vector<int>> g(n + 1), fg(n + 1);
    int rt = 0;
    for (int i = 1; i <= n; ++i) {
        int x;
        cin >> x;
        if (x == -1) {
            rt = i;
        } else {
            g[i].push_back(x);
            fg[x].push_back(i);
        }
    }
    vector<int> vis(n + 1), dep(n + 1);
    vis[rt] = 0;
    int Maxdep = 0;
    int Length = 0;
    auto dfs1 = [&](auto&& dfs, int u) -> void {
        for (auto v : fg[u]) {
            dep[v] = dep[u] + 1;
            dfs(dfs, v);
        }
    };
    dfs1(dfs1, rt);
    vis[rt] = 1;
    auto dfs = [&](auto&& dfs, int u, int step) -> void {
        // cout << '*' << u << endl;
        if (vis[u]) {
            Length += step;
            return;
        }
        vis[u] = 1;
        for (auto v : g[u]) {
            dfs(dfs, v, step + 1);
        }
    };
    for (int i = 1; i <= m; ++i) {
        int x;
        cin >> x;
        Maxdep = max(dep[x], Maxdep);
        dfs(dfs, x, 0);
        cout << Length * 2 - Maxdep << '\n';
    }
}

int32_t main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    int T = 1;
    // cin >> T;
    while (T--) {
        ylh_();
    }
}

L2-044 大众情人

建立距离矩阵用floyd求最短路即可

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int INF = 2e9;

void ylh_() {
    int n;
    cin >> n;
    vector<int> sex(n + 1);
    vector<vector<int>> dist(n + 1, vector<int>(n + 1, INF));
    for (int i = 1; i <= n; ++ i) {
        dist[i][i] = 0;
        char c;
        cin >> c;
        sex[i] = (c == 'M');
        int k;
        cin >> k;
        for (int j = 1; j <= k; ++ j) {
        	int p, x;
        	cin >> p >> c >> x;
        	dist[i][p] = x;
		}
    }
    for (int k = 1; k <= n; ++ k) {
    	for (int i = 1; i <= n; ++ i) {
    		for (int j = 1; j <= n; ++ j) {
    			dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
			}
		}
	}
	int Min1 = INF, Min2 = INF;
	vector<int> ans1, ans2;
    for (int i = 1; i <= n; ++ i) {
    	int Max = 0;
    	for (int j = 1; j <= n; ++ j) {
    		if (i == j) continue;
    		if (sex[i] == sex[j]) continue;
    		Max = max(dist[j][i], Max);
		}
		if (sex[i] == 0) {
			if (Min1 > Max) {
				Min1 = Max;
				ans1.clear();
				ans1.push_back(i);
			} else if (Min1 == Max) {
				ans1.push_back(i);
			}
		} else {
			if (Min2 > Max) {
				Min2 = Max;
				ans2.clear();
				ans2.push_back(i);
			} else if (Min2 == Max) {
				ans2.push_back(i);
			}
		}
	}
	for (int i = 0; i < ans1.size(); ++ i) {
		if (i != 0) {
			cout << ' ';
		}
		cout << ans1[i];
	}
	cout << '\n';
	for (int i = 0; i < ans2.size(); ++ i) {
		if (i != 0) {
			cout << ' ';
		}
		cout << ans2[i];
	}
	cout << '\n';
}

int32_t main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    int T = 1;
    // cin >> T;
    while (T--) {
        ylh_();
    }
}

L2-045 堆宝塔

不是很复杂的模拟,依照题意写就行了

#include <bits/stdc++.h>
using namespace std;
#define int long long

void ylh_() {
    int n;
    cin >> n;
    vector<int> a(n + 1);
    for (int i = 1; i <= n; ++i) {
        cin >> a[i];
    }
    stack<int> st1, st2;
    int ans1 = 0, ans2 = 0;
    for (int i = 1; i <= n; ++i) {
        if (st1.empty()) {
            st1.push(a[i]);
        } else {
            if (a[i] < st1.top()) {
                st1.push(a[i]);
            } else {
                if (st2.empty()) {
                    st2.push(a[i]);
                } else {
                    if (a[i] > st2.top()) {
                        st2.push(a[i]);
                    } else {
                        ++ans1;
                        ans2 = max((int)st1.size(), ans2);
                        while (!st1.empty()) {
                            st1.pop();
                        }
                        while (!st2.empty() && st2.top() > a[i]) {
                            st1.push(st2.top());
                            st2.pop();
                        }
                        st1.push(a[i]);
                    }
                }
            }
        }
    }
    if (st2.size()) {
        ++ans1;
        ans2 = max((int)st2.size(), ans2);
    }
    if (st1.size()) {
        ++ans1;
        ans2 = max((int)st1.size(), ans2);
    }
    cout << ans1 << ' ' << ans2;
}

int32_t main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    int T = 1;
    // cin >> T;
    while (T--) {
        ylh_();
    }
}

L2-046 天梯赛的赛场安排

题目依旧讲不清白
每个学校的监考人数是学校的学生分配去的考场数
因为只要遇见大于c的就直接开一个考场塞满,对答案没影响,这一部分可以优化掉,就不会超时

#include <bits/stdc++.h>
using namespace std;
#define int long long
using PII = pair<int, int>;

void ylh_() {
    int n, c;
    cin >> n >> c;
    int ans = 0;
    vector<string> name(n + 1);
    vector<PII> num(n + 1);
    vector<int> cnt(n + 1);
    for (int i = 1; i <= n; ++i) {
        cin >> name[i] >> num[i].first;
        cnt[i] += num[i].first / c;
        ans += cnt[i];
        num[i].first %= c;
        num[i].second = i;
    }
    vector<int> Room;
    sort(num.begin() + 1, num.end(), greater<PII>());
    for (int i = 1; i <= n; ++i) {
        auto [val, idx] = num[i];
        if (val == 0)
            continue;
        int find = 0;
        for (auto& person : Room) {
            if (person + val <= c) {
                person += val;
                find = 1;
                cnt[idx]++;
                break;
            }
        }
        if (!find) {
            Room.push_back(val);
            cnt[idx]++;
        }
    }
    for (int i = 1; i <= n; ++i) {
        cout << name[i] << ' ' << cnt[i] << '\n';
    }
    cout << ans + Room.size();
}

int32_t main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    int T = 1;
    // cin >> T;
    while (T--) {
        ylh_();
    }
}

L2-047 锦标赛

#include <bits/stdc++.h>
using namespace std;
#define int long long
using PII = pair<int, int>;

void ylh_() {
    int t;
    cin >> t;
    vector<PII> tr(1 << 20); // PII第一维表示败者,二维表示胜者,按照每场比赛为节点建立完美二叉树
    for (int i = 1; i <= t; ++i) {
        for (int j = (1 << (t - i)); j <= (1 << (t - i + 1)) - 1; ++j) {
            cin >> tr[j].first;
        }
    }
    cin >> tr[1].second;
    auto dfs = [&](auto&& dfs, int u) -> bool {
        if (u > ((1 << t) - 1))
            return true;
        if (tr[u].first > tr[u].second) {
            return false;
        }
        tr[u << 1].second = tr[u].first;
        tr[(u << 1) + 1].second = tr[u].second;
        if (dfs(dfs, u << 1) && dfs(dfs, (u << 1) + 1))
            return true;
        swap(tr[u << 1].second, tr[(u << 1) + 1].second);
        if (dfs(dfs, u << 1) && dfs(dfs, (u << 1) + 1))
            return true;
        return false;
    };
    if (dfs(dfs, 1)) {
        for (int i = (1 << t - 1); i <= (1 << t) - 1; ++i) {
            if (i != (1 << t) - 1) {
                cout << tr[i].first << ' ' << tr[i].second << ' ';
            } else {
                cout << tr[i].first << ' ' << tr[i].second;
            }
        }
    } else {
        cout << "No Solution";
    }
}

int32_t main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    int T = 1;
    // cin >> T;
    while (T--) {
        ylh_();
    }
}

L2-048 寻宝图

纯血经典搜索题

#include <bits/stdc++.h>
using namespace std;
#define int long long

int dx[4] = { 0, 1, 0, -1 };
int dy[4] = { 1, 0, -1, 0 };

void ylh_() {
    int n, m;
    cin >> n >> m;
    vector<string> a(n + 1);
    vector<vector<int>> vis(n + 1, vector<int>(m + 1));
    int find = 0;
    for (int i = 1; i <= n; ++i) {
        cin >> a[i];
        a[i] = " " + a[i];
    }
    auto dfs = [&](auto&& dfs, int x, int y) -> void {
        if (vis[x][y])
            return;
        if (a[x][y] != '1') {
            find = 1;
        }
        vis[x][y] = 1;
        for (int i = 0; i < 4; ++i) {
            int nx = dx[i] + x;
            int ny = dy[i] + y;
            if (nx < 1 || nx > n || ny < 1 || ny > m)
                continue;
            if (a[nx][ny] == '0') {
                continue;
            }
            dfs(dfs, nx, ny);
        }
    };
    int ans1 = 0, ans2 = 0;
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= m; ++j) {
            if (a[i][j] != '0' && !vis[i][j]) {
                ++ans1;
                find = 0;
                dfs(dfs, i, j);
                ans2 += find;
            }
        }
    }
    cout << ans1 << ' ' << ans2;
}

int32_t main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    int T = 1;
    // cin >> T;
    while (T--) {
        ylh_();
    }
}

L2-049 鱼与熊掌

set搞一下就行了

#include <bits/stdc++.h>
using namespace std;
#define int long long

void ylh_() {
    int n, m;
    cin >> n >> m;
    vector<set<int>> st(n + 1);
    for (int i = 1; i <= n; ++i) {
        int k;
        cin >> k;
        for (int j = 1; j <= k; ++j) {
            int x;
            cin >> x;
            st[i].insert(x);
        }
    }
    int q;
    cin >> q;
    while (q--) {
        int x, y;
        cin >> x >> y;
        int ans = 0;
        for (int i = 1; i <= n; ++i) {
            if (st[i].count(x) && st[i].count(y)) {
                ++ans;
            }
        }
        cout << ans << '\n';
    }
}

int32_t main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    int T = 1;
    // cin >> T;
    while (T--) {
        ylh_();
    }
}

L2-050 懂蛇语

注意空格分隔不止一个空格,所以要用getline读入

#include <bits/stdc++.h>
using namespace std;
#define int long long

void ylh_() {
    int n;
    cin >> n;
    map<string, vector<string>> mp;
    for (int i = 1; i <= n; ++i) {
        string s = "", t = "";
        if (i == 1) {
            getline(cin, s);
        }
        getline(cin, s);
        for (int i = 0; i < s.length(); ++i) {
            if (s[i] >= 'a' && s[i] <= 'z' && (i == 0 || s[i - 1] == ' ')) {
                t += s[i];
            }
        }
        mp[t].push_back(s);
    }
    for (auto& [x, vec] : mp) {
        sort(vec.begin(), vec.end());
    }
    int m;
    cin >> m;
    for (int i = 1; i <= m; ++i) {
        string s = "", t = "";
        if (i == 1) {
            getline(cin, s);
        }
        getline(cin, s);
        for (int i = 0; i < s.length(); ++i) {
            if (s[i] >= 'a' && s[i] <= 'z' && (i == 0 || s[i - 1] == ' ')) {
                t += s[i];
            }
        }
        if (!mp[t].size()) {
            cout << s << '\n';
        }
        for (int i = 0; i < mp[t].size(); ++i) {
            cout << mp[t][i] << "|\n"[i == mp[t].size() - 1];
        }
    }
}

int32_t main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    int T = 1;
    // cin >> T;
    while (T--) {
        ylh_();
    }
}

L2-051 满树的遍历

其实我不太懂这种非二叉树的前序遍历是个什么玩意,于是按顺序遍历试了一下发现过了

#include <bits/stdc++.h>
using namespace std;
#define int long long

const int MOD = 998244353;
using PII = pair<int, int>;

void ylh_() {
    int n;
    cin >> n;
    vector<vector<int>> g(n + 1);
    int rt = -1;
    vector<int> degree(n + 1); // 度数的出现次数
    for (int i = 1; i <= n; ++i) {
        int x;
        cin >> x;
        if (x == 0)
            rt = i;
        else {
            g[x].push_back(i);
        }
    }
    vector<int> ans;
    auto dfs = [&](auto&& dfs, int u) -> void {
        int deg = 0;
        ans.push_back(u);
        for (auto v : g[u]) {
            dfs(dfs, v);
            ++deg;
        }
        degree[deg]++;
    };
    dfs(dfs, rt);
    int cnt = 0;
    int Max = -1;
    for (int i = 0; i <= n; ++i) {
        if (degree[i] != 0) {
            ++cnt;
            Max = i;
        }
    }
    if (cnt >= 3) {
        cout << Max << ' ' << "no" << '\n';
    } else {
        cout << Max << ' ' << "yes" << '\n';
    }
    for (int i = 0; i < n; ++i) {
        cout << ans[i] << " \n"[i == n - 1];
    }
}

int32_t main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    int T = 1;
    // cin >> T;
    while (T--) {
        ylh_();
    }
}

L2-052 吉利矩阵

其实就是爆搜剪枝,我想了一下数据小就没仔细思考了,每次剪一点点剪了三次小点就过了
可以专门用数组记录行列和,然后超出就剪枝
实际上可以根据每行或者每列的前n -1个数确定最后一个数,可以缩小指数
甚至可以得出答案后打表也是可以的

#include <bits/stdc++.h>
using namespace std;
#define int long long

using PII = pair<int, int>;

void ylh_() {
    int l, n;
    cin >> l >> n;
    vector<vector<int>> a(n + 1, vector<int>(n + 1));
    int ans = 0;
    auto dfs = [&](auto&& dfs, int x, int y) -> void {
        if (x == n + 1) {
            for (int j = 1; j <= n; j++) {
                int s = 0;
                for (int i = 1; i <= n; i++)
                    s += a[i][j];
                if (s != l)
                    return;
            }
            ans++;
            return;
        }
        if (y == n + 1) {
            int s = 0;
            for (int i = 1; i <= n; i++)
                s += a[x][i];
            if (s != l)
                return;
            dfs(dfs, x + 1, 1);
            return;
        }
        int s = 0;
        for (int i = 1; i < y; i++)
            s += a[x][i];
        if (s > l)
            return;
        s = 0;
        for (int i = 1; i < x; ++i) {
            s += a[i][y];
        }
        if (s > l)
            return;
        for (int v = 0; v <= l; v++) {
            if (s + v > l)
                continue;
            a[x][y] = v;
            if (x == n) {
                int t = 0;
                for (int i = 1; i <= n; i++)
                    t += a[i][y];
                if (t != l)
                    continue;
            }
            dfs(dfs, x, y + 1);
        }
    };
    dfs(dfs, 1, 1);
    cout << ans << '\n';
}

int32_t main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    int T = 1;
    // cin >> T;
    while (T--) {
        ylh_();
    }
}

L2-053 算式拆解

如果你WA2了,注意数字可能很长,超出longlong范围
但是实际上我们并不需要算出来的数字,所以用字符串存就好了
甚至有更简单好写的做法,但我懒得写了

#include <bits/stdc++.h>
using namespace std;
#define int long long

void ylh_() {
    string s;
    cin >> s;
    int n = s.length();
    stack<string> num;
    stack<char> op;
    auto work = [&]() -> void {
        auto b = num.top();
        num.pop();
        auto a = num.top();
        num.pop();
        char c = op.top();
        op.pop();
        int res = 0;
        if (b == "OooOOOO00O0o" && a == "OooOOOO00O0o") {
            cout << c << '\n';
        } else if (a == "OooOOOO00O0o" && b != "OooOOOO00O0o") {
            cout << c << b << '\n';
        } else if (b == "OooOOOO00O0o" && a != "OooOOOO00O0o") {
            cout << a << c << '\n';
        } else {
            cout << a << c << b << '\n';
        }
        num.push({ "OooOOOO00O0o" });
    };

    for (int i = 0; i < n; ++i) {
        if (isdigit(s[i])) {
            int j = i;
            string cur;
            while (j < n && isdigit(s[j])) {
                cur += s[j];
                ++j;
            }
            i = j - 1;
            num.push({ cur });
        } else if (s[i] == '(') {
            continue;
        } else if (s[i] == ')') {
            work();
        } else {
            op.push(s[i]);
        }
    }
}

int32_t main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    int T = 1;
    // cin >> T;
    while (T--) {
        ylh_();
    }
}

L2-054 三点共线

如果只枚举两个点那么复杂度会大大减少,因为题目按照1,0排序,所以我们按这个顺序枚举就行,卡卡常剪剪枝就能过

#include <bits/stdc++.h>
using namespace std;

const int N = 1e6;
int st[3][N * 2 + 10];//全局数组更快

void ylh_() {
    int n;
    cin >> n;
    vector<vector<int>> seg(3);
    for (int i = 1; i <= n; ++i) {
        int x, y;
        cin >> x >> y;
        if (!st[y][x + N]) {
            seg[y].push_back(x);
        }
        st[y][x + N] = 1;
    }
    for (int i = 0; i <= 1; ++i) {
        sort(seg[i].begin(), seg[i].end());
    }
    auto print = [&](int x1, int y1, int x2, int y2, int x3, int y3) {
        cout << '[' << x1 << ", " << y1 << "] ";
        cout << '[' << x2 << ", " << y2 << "] ";
        cout << '[' << x3 << ", " << y3 << "]\n";
    };
    int f = 0;
    for (int x1 : seg[1]) {
        for (int x0 : seg[0]) {//存答案还要排序可能更慢,这样不用存
            int x2 = 2 * x1 - x0;
            if (x2 > N)
                continue;
            if (x2 < -N)
                break;//自己手画一下发现这个可以改成break,是一个剪枝
            if (st[2][x2 + N]) {
                f = 1;
                print(x0, 0, x1, 1, x2, 2);
            }
        }
    }
    if (!f) {
        cout << -1;
    }
}

int32_t main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    int T = 1;
    // cin >> T;
    while (T--) {
        ylh_();
    }
}

L2-055 胖达的山头

简单差分

#include <bits/stdc++.h>
using namespace std;
#define int long long

void ylh_() {
    int n;
    cin >> n;
    vector<int> a(24 * 3600 + 10);
    for (int i = 1; i <= n; ++ i) {
        int h, m, s, time;
        char c;
        cin >> h >> c >> m >> c >> s;
        time = h * 3600 + m * 60 + s;
        a[time]++;
        cin >> h >> c >> m >> c >> s;
        time = h * 3600 + m * 60 + s;
        a[time + 1]--;
    }
    int ans = a[0];
    for (int i = 1; i <= 24 * 3600; ++ i) {
        a[i] += a[i - 1];
        ans = max(a[i], ans);
    }
    cout << ans;
}

int32_t main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    int T = 1;
    // cin >> T;
    while (T--) {
        ylh_();
    }
}

L2-056 被n整除的n位数

感觉答案不会太多,所以爆搜试试,发现可过

#include <bits/stdc++.h>
using namespace std;
#define int long long

void ylh_() {
    int n, a, b;
    cin >> n >> a >> b;
    int f = 0;
    int val = 0;
    auto dfs = [&](auto&& dfs, int w) {
        if (w == n) {
            if (val >= a && val <= b) {
                f = 1;
                cout << val << '\n';
            }
            return;
        }
        for (int i = 0; i <= 9; ++i) {
            if (w == 0 && i == 0)
                continue;
            val = val * 10 + i;
            if (val % (w + 1) == 0) {
                dfs(dfs, w + 1);
            }
            val /= 10;
        }
    };
    dfs(dfs, 0);
    if (!f) {
        cout << "No Solution";
    }
}

int32_t main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    int T = 1;
    // cin >> T;
    while (T--) {
        ylh_();
    }
}
posted @ 2026-07-08 10:09  ylh-  阅读(8)  评论(0)    收藏  举报