C. Manipulating History
神仙偷鸡题
题意
初始时存在长度为 1 1 1 的字符串 s s s,每次操作可选中 s s s 中的一个子串 a a a,并将该子串替换成一个指定的字符串 b b b,进行了 t 次操作后将得到字符串 s ′ s' s′ 。现在给定最后得到的字符串 s ′ s' s′,以及在 t t t 次操作中所有的 a i a_i ai 和 b i b_i bi (但打乱顺序),求初始字符串 s s s 。
神仙偷鸡题,对于字符串 s ′ s' s′ 中存在而 s s s 中不存在的字符,一定是在 t t t 次操作过程中至少通过一次有效操作使得对应字符添加到 s s s 中。而对于类似 a − > b c , b c − > a a->bc,bc->a a−>bc,bc−>a 且 b c bc bc 不存在于 s s s 和 s ′ s' s′ 中的无效操作,可以发现一定是呈偶数次出现的,且最后给出的字符串 s ′ s' s′ 能够与所有有效操作带来的贡献进行抵消,因此可将本题转为奇偶性判断。
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 4e5 + 10;
string s[N];
int a[N];
map<char, int> mp;
void solve() {
int n;
cin >> n;
string s;
mp.clear();
for (int i = 1; i <= 2 * n + 1; i++) {
cin >> s;
for (int j = 0; j < s.length(); j++) {
mp[s[j]]++;
}
}
for (auto i : mp) {
if (i.second % 2 == 1) {
cout << i.first << endl;
return;
}
}
}
signed main() {
int t = 1;
cin >> t;
while (t--)
solve();
return 0;
}
D. The Enchanted Forest
题意
可选择从任意起点开始,每个单位时间能移动到相邻结点(或选择不移动)并得到对应贡献值,之后该位上的贡献值将清零。同时每个单位时间之后,所有位上的贡献值都将 + 1 +1 +1 ,求 k k k 时间内能够得到的最大贡献。
容易贪心得到,当 k ≤ n k≤n k≤n 时,最优解为选择连续区间和最大的。当 k > n k>n k>n 时,需要尽可能在端点间往返使单位时间贡献最大化。手模可发现:当 n = 5 n=5 n=5 且初始全为 0 0 0 时,从左向右收割一遍后将得到序列 5 4 3 2 1 5\ 4\ 3\ 2\ 1 5 4 3 2 1 ( + 1 +1 +1 操作在收割之后),即最后会剩下 n ∗ ( n + 1 ) 2 \frac{n*(n+1)}{2} 2n∗(n+1) ,而总增长为 n ∗ k n*k n∗k,则总增长-剩余=贡献
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 2e5 + 10;
int a[N], s[N];
void solve() {
int n, k;
cin >> n >> k;
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
for (int i = 1; i <= n; i++) {
s[i] = s[i - 1] + a[i];
}
int res = 0;
if (k >= n) {
res += s[n] + k - n + (n - 1) * (k - n + 1 + k - 1) / 2;
cout << res << endl;
} else {
for (int i = 1; i + k - 1 <= n; i++)
res = max(res, s[i + k - 1] - s[i - 1]);
res += (k - 1) * k / 2;
cout << res << endl;
}
}
signed main() {
int t = 1;
cin >> t;
while (t--)
solve();
return 0;
}