Day 10
Day 10
早上
两片面包 + 橙汁 + 黄油.
上午
模拟赛.
T1 假了 T2 不会 T3 不会 T4 没记忆化
T1 数据有锅所以给我 \(100pts\) 了
赛后重测飞了.
中午
我给出题人绑来啦!
开始审讯出题人.
吃了一个披萨 + 意大利面 + 可乐.
依旧三国杀.
睁开你的眼睛看看, 现在是谁说了算!

下午
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\) 为空, 每次可任选其一:
- 删除 \(S\) 的首字符, 追加到 \(T\) 末尾;
- 删除 \(S\) 的尾字符, 追加到 \(T\) 末尾;
- 若 \(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 的问题, 在群里发生了一些争吵.
我发了一句


炸出来一堆三国杀

下午休息
休息就是瞎颓, 晚饭吃的肠粉. 肚子不大舒服.
后来玩了会麻将.
zyq 晚上在学多项式全家桶, 现在还在学.
差不多吧, 今天就写到这里.
明天是杂题精讲. 是不是 Djangle 讲课啊.

浙公网安备 33010602011771号