2024.12.23 周一
Q1. 1100
Alice and Bob are playing a game. They have an array $a_1, a_2,\ldots,a_n$. The game consists of two steps:
- First, Alice will remove at most $k$ elements from the array.
- Second, Bob will multiply at most $x$ elements of the array by $-1$.
Alice wants to maximize the sum of elements of the array while Bob wants to minimize it. Find the sum of elements of the array after the game if both players play optimally.
Q2. 1100
You are given a string $s$ of length $n$. Let's define two operations you can apply on the string:
- remove the first character of the string;
- remove the second character of the string.
Your task is to find the number of distinct non-empty strings that can be generated by applying the given operations on the initial string any number of times (possibly zero), in any order.
Q3. 1100
Monocarp is playing a computer game. In order to level up his character, he can complete quests. There are $n$ quests in the game, numbered from $1$ to $n$.
Monocarp can complete quests according to the following rules:
- the $1$-st quest is always available for completion;
- the $i$-th quest is available for completion if all quests $j < i$ have been completed at least once.
Note that Monocarp can complete the same quest multiple times.
For each completion, the character gets some amount of experience points:
- for the first completion of the $i$-th quest, he gets $a_i$ experience points;
- for each subsequent completion of the $i$-th quest, he gets $b_i$ experience points.
Monocarp is a very busy person, so he has free time to complete no more than $k$ quests. Your task is to calculate the maximum possible total experience Monocarp can get if he can complete no more than $k$ quests.
Q4. 1100
You are given a tree$^{\dagger}$. In one zelda-operation you can do follows:
- Choose two vertices of the tree $u$ and $v$;
- Compress all the vertices on the path from $u$ to $v$ into one vertex. In other words, all the vertices on path from $u$ to $v$ will be erased from the tree, a new vertex $w$ will be created. Then every vertex $s$ that had an edge to some vertex on the path from $u$ to $v$ will have an edge to the vertex $w$.
Illustration of a zelda-operation performed for vertices $1$ and $5$.
Determine the minimum number of zelda-operations required for the tree to have only one vertex.
$^{\dagger}$A tree is a connected acyclic undirected graph.
------------------------独自思考分割线------------------------
-
用时:32 8 8 40(-1)。1、2、4有意思。1、3用到了遍历维护思想,可找 $n$ 种方案的最优解。4观察结论还是从小数据更易发现思路,树还是定根更好看。
A1.
- 一开始没思考本质出了个假思路:删除最大的min(k,x)个元素。
- It is optimal for Bob to negate the $x$ largest elements of the array. So in order to minimize the damage Bob will do, Alice should always remove some number of largest elements.
- To solve the problem, we can sort the array and iterate over $i$ ($0 \leq i \leq k$) where $i$ is the number of elements Alice removes. For each $i$, we know that Alice will remove the $i$ largest elements of the array and Bob will then negate the $x$ largest remaining elements.
- 前缀和/扫过去变量维护(细节处理)。
A2.
- 考虑长度 $1$ ~ $n$ 的字符串数,由于只能删除第一个/第二个字母,最后的字符串的后 $len-1$个字母一定是源字符串的后缀。
- 结论:不同字符数的前缀和之和。
A3.
- 一眼。后面由前面限制,遍历维护求最大值。
- So the answer to the problem is the maximum of $\sum\limits_{j=1}^{i} a_j + \max\limits_{j=1}^{i} b_j \cdot (k - i)$ over all values of $i$ from $1$ to $\min(n, k)$. Note that the value of $n$ is too large to calculate sums and maximums in the aforementioned formula every time (for each $i$ independently), so you have to maintain these values as the value for $i$ grows.
A4.
- 出了假思路:每次操作减少一片叶子-> $1片/2片$。
- 结论观察。在有根树的视图更易找结论,或从点少的树开始找最优结论:前 $n-1$ 次每次可减少2片叶子。
We can prove by induction that on any tree with $K$ leaves, the answer is $[{\frac{K + 1}{2}}]$, where with $[x]$ we denote the greatest integer smaller than $x$. This can be proven by induction, we will give an overview of what a proof would look like:
- For two leaves, the answer is clearly $1$.
- For three leaves, the answer is clearly $2$.
- For more than four leaves, it is always the case that we can find two leaves for which the node that will be created as a result of applying an operation on these two will have degree greater than $1$ (i.e. it will not be a leaf)
The third argument holds because in a tree with four leaves, we have either at least two nodes with degree at least $3$ (and as such we can choose two leaves which contain these two nodes on their chain), or a node with degree at least $4$. Furthermore, it reduces the number of leaves in the tree by $2$.
------------------------代码分割线------------------------
A1.
#include <bits/stdc++.h>
#define int long long //
#define endl '\n' // 交互/调试 关
using namespace std;
#define bug(BUG) cout << "bug:# " << (BUG) << endl
#define bug2(BUG1, BUG2) cout << "bug:# " << (BUG1) << " " << (BUG2) << endl
#define bug3(BUG1, BUG2, BUG3) cout << "bug:# " << (BUG1) << ' ' << (BUG2) << ' ' << (BUG3) << endl
void _();
signed main()
{ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);cout << fixed << setprecision(6);int T = 1;cin >> T;while (T--)_();return 0;
}void _()
{int n, k, x;cin >> n >> k >> x;vector<int> a(n + 1);for (int i = 1; i <= n; i++)cin >> a[i];sort(a.begin() + 1, a.end());int un_neg = 0, neg = 0;for (int i = 1; i <= n - x; i++)un_neg += a[i];for (int i = n - x + 1; i <= n; i++)neg += -a[i];int res = un_neg + neg;int st = n - x, ed = n;int cnt = 0;while (ed >= 0 && ++cnt <= k){un_neg -= a[st];neg += -a[st] + a[ed];res = max(res, un_neg + neg);// bug3(st, un_neg, neg);st--, ed--;st = max(0ll, st);}cout << res << endl;// 假思路// int move = min(x, k);// int mul = max(0ll, x - k);// int res = 0;// for (int i = move; i < n; i++)// res += i - move < mul ? -a[i] : a[i];// cout << res << endl;
}
A2.
#include <bits/stdc++.h>
#define int long long //
#define endl '\n' // 交互/调试 关
using namespace std;
#define bug(BUG) cout << "bug:# " << (BUG) << endl
#define bug2(BUG1, BUG2) cout << "bug:# " << (BUG1) << " " << (BUG2) << endl
#define bug3(BUG1, BUG2, BUG3) cout << "bug:# " << (BUG1) << ' ' << (BUG2) << ' ' << (BUG3) << endl
void _();
signed main()
{ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);cout << fixed << setprecision(6);int T = 1;cin >> T;while (T--)_();return 0;
}void _()
{int n;cin >> n;string s;cin >> s;map<char, int> cnt;int res = 0;for (auto v : s){cnt[v]++;res += cnt.size();}cout << res << endl;
}
A3.
#include <bits/stdc++.h>
#define int long long //
#define endl '\n' // 交互/调试 关
using namespace std;
#define bug(BUG) cout << "bug:# " << (BUG) << endl
#define bug2(BUG1, BUG2) cout << "bug:# " << (BUG1) << " " << (BUG2) << endl
#define bug3(BUG1, BUG2, BUG3) cout << "bug:# " << (BUG1) << ' ' << (BUG2) << ' ' << (BUG3) << endl
void _();
signed main()
{ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);cout << fixed << setprecision(6);int T = 1;cin >> T;while (T--)_();return 0;
}void _()
{int n, k;cin >> n >> k;vector<int> a(n + 1), b(n + 1);for (int i = 1; i <= n; i++)cin >> a[i];for (int i = 1; i <= n; i++)cin >> b[i];int maxb = b[1], pre = a[1];int res = pre + (k - 1) * maxb;for (int i = 2; i <= n && i <= k; i++){pre += a[i];maxb = max(maxb, b[i]);int ans = pre + max(0ll, k - i) * maxb;res = max(res, ans);}cout << res << endl;
}
A4
#include <bits/stdc++.h>
#define int long long //
#define endl '\n' // 交互/调试 关
using namespace std;
#define bug(BUG) cout << "bug:# " << (BUG) << endl
#define bug2(BUG1, BUG2) cout << "bug:# " << (BUG1) << " " << (BUG2) << endl
#define bug3(BUG1, BUG2, BUG3) cout << "bug:# " << (BUG1) << ' ' << (BUG2) << ' ' << (BUG3) << endl
void _();
signed main()
{ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);cout << fixed << setprecision(6);int T = 1;cin >> T;while (T--)_();return 0;
}void _()
{int n;cin >> n;vector<int> d(n + 1);vector<vector<int>> e(n + 1);for (int i = 1; i < n; i++){int u, v;cin >> u >> v;e[u].push_back(v);e[v].push_back(u);d[u]++, d[v]++;}int leaf = 0;for (int i = 1; i <= n; i++)leaf += d[i] == 1;cout << (leaf + 1 >> 1) << endl;// int leaf = 0, special_leaf = 0;// for (int i = 1; i <= n; i++)// {// if (d[i] == 1)// {// int p = e[i][0];// // bug2(i, e[i][0]);// if (d[p] > 2)// special_leaf++;// else// leaf++;// }// }// if (leaf < 2)// {// int d = 2 - leaf;// leaf += d;// special_leaf -= d;// }// // bug2(leaf, special_leaf);// int res = (special_leaf + 1 >> 1) + leaf - 1;// cout << res << endl;
}