Day 10

Day 10

早上

两片面包 + 橙汁 + 黄油.

上午

模拟赛.

T1 假了 T2 不会 T3 不会 T4 没记忆化

T1 数据有锅所以给我 \(100pts\)

赛后重测飞了.

中午

我给出题人绑来啦!

开始审讯出题人.

吃了一个披萨 + 意大利面 + 可乐.

依旧三国杀.

睁开你的眼睛看看, 现在是谁说了算!

image

下午

T1

给定一棵以 1 为根的有根树, 每个节点有权值 \(a_i\), 且 \(a_1=0\).
需要选择一个包含根节点 1 的“关键节点”集合. 除 1 外, 集合中的节点视为新增关键点.
每个非根节点会分配给最近的严格祖先关键节点(即使自身是关键点, 也分配给上方的关键点). 根节点不分配.
每个关键节点管理所有分配给它的节点, 要求每个管理区域内所有节点权值之和不超过给定上限 \(m_0\).
求最少需要新增多少个关键节点, 若无法满足要求则输出 \(-1\).

DP 乱搞.

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

namespace OI {

#define int long long
#define endl "\n"

constexpr int maxn = 3e5 + 5;

vector<int> graph[maxn];
int a[maxn], f[maxn];
int n, m;
int ans = 0;
bool legal = true;

bool isLeaf(int u) {
    return (u != 1 && graph[u].size() == 1);
}

void dfs(int u, int fa) {
    if (isLeaf(u)) {
        f[u] = a[u];
        if (f[u] > m)
            legal = false;
        return;
    }

    f[u] = 0;
    priority_queue<int> heap;

    for (int v : graph[u]) {
        if (v == fa)
            continue;
        dfs(v, u);
        if (!legal)
            return;
        f[u] += f[v];
        heap.push(f[v] - a[v]);
    }

    while (f[u] > m && !heap.empty()) {
        int x = heap.top();
        heap.pop();
        f[u] -= x;
        ans++;
        if (f[u] <= m)
            break;
    }

    if (f[u] > m) {
        legal = false;
        return;
    }

    f[u] += a[u];

    if (f[u] > m) {
        f[u] = a[u];
        if (f[u] > m) {
            legal = false;
            return;
        }
        ans++;
    }
}

void main() {
    cin >> n >> m;
    for (int i = 1; i <= n; i++)
        cin >> a[i];

    for (int i = 1; i < n; i++) {
        int u, v;
        cin >> u >> v;
        graph[u].push_back(v);
        graph[v].push_back(u);
    }

    if (n == 1) {
        cout << (a[1] <= m ? 0 : -1) << endl;
        return;
    }

    dfs(1, 0);

    if (!legal)
        cout << -1 << endl;
    else
        cout << ans << endl;
}

#undef int
#undef endl

} // namespace OI

int main() {
    freopen("dyson.in", "r", stdin);
    freopen("dyson.out", "w", stdout);

    cin.tie(0), cout.tie(0);
    ios::sync_with_stdio(0);

    OI::main();

    return 0;
}

T2

给定一个小写字母字符串 \(S\), 初始 \(T\) 为空. 反复执行以下操作直到 \(S\) 为空, 每次可任选其一:

  1. 删除 \(S\) 的首字符, 追加到 \(T\) 末尾;
  2. 删除 \(S\) 的尾字符, 追加到 \(T\) 末尾;
  3. \(S\) 能写成 \(A\,B\,A^R\)\(A\) 非空, \(A^R\)\(A\) 的反串), 则令 \(S=B\), 并把 \(A\) 整个追加到 \(T\) 末尾.

求所有操作方案下, 能得到的字典序最小的 \(T\).

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

namespace OI {

#define int long long
#define endl "\n"

int t, cnt[30];
string S, T;

bool check(int x) {
    for (int i = 0; i < 26; i++)
        if (i != x && cnt[i])
            return 0;
    return 1;
}

void main() {
    cin >> t;
    while (t--) {
        cin >> S;
        T = "";
        for (int i = 0; i < 26; i++)
            cnt[i] = 0;
        for (int i = 0; i < S.size(); i++)
            cnt[S[i] - 'a']++;
        int l = 0, r = S.size() - 1;
        while (l < r) {
            if (S[l] < S[r])
                T += S[l],
                cnt[S[l] - 'a']--,
                l++;
            else if (S[r] < S[l])
                T += S[r],
                cnt[S[r] - 'a']--,
                r--;
            else {
                if (check(S[l] - 'a'))
                    T += S[l],
                    cnt[S[l] - 'a'] -= 2,
                    l++,
                    r--;
                else {
                    int L = l + 1, R = r - 1;
                    while (S[L] == S[l])
                        L++;
                    while (S[R] == S[r])
                        R--;
                    int cntL = L - l, cntR = r - R;
                    if (S[L] > S[l] && S[R] > S[r]) {
                        for (int i = 1; i <= cntL + cntR; i++)
                            T += S[l];
                        cnt[S[l] - 'a'] -= cntL + cntR,
                        l = L,
                        r = R; 
					}
					else if (S[L] < S[l] && S[R] > S[r]) {
                        for (int i = 1; i <= cntL; i++)
                            T += S[l];
                        cnt[S[l] - 'a'] -= cntL,
                        l = L;
					}
					else if (S[L] > S[l] && S[R] < S[r]) {
                        for (int i = 1; i <= cntR; i++)
                            T += S[r];
                        cnt[S[r] - 'a'] -= cntR,
                        r = R;
					}
					else if (S[L] < S[l] && S[R] < S[r]) {
                        int Cnt = min(cntL, cntR);
                        for (int i = 1; i <= Cnt; i++)
                            T += S[l];
                        cnt[S[l] - 'a'] -= 2 * Cnt,
                        l = l + Cnt,
                        r = r - Cnt;
					}
                }
            }
        }
        T += S[r],
        cnt[S[r] - 'a']--;
        cout << T << endl;
    }
}

#undef int
#undef endl

}

int main() {
    freopen("jump3.in", "r", stdin);
    freopen("jump3.out", "w", stdout);

    cin.tie(0), cout.tie(0);
    ios::sync_with_stdio(0);

    OI::main();

    return 0;
}

由于 T1 的问题, 在群里发生了一些争吵.

我发了一句

p1
p2

炸出来一堆三国杀

这期神了

下午休息

休息就是瞎颓, 晚饭吃的肠粉. 肚子不大舒服.

后来玩了会麻将.

zyq 晚上在学多项式全家桶, 现在还在学.

差不多吧, 今天就写到这里.

明天是杂题精讲. 是不是 Djangle 讲课啊.

返回目录

posted @ 2026-08-04 23:42  Kibrel  阅读(1)  评论(0)    收藏  举报