cf1688C. Manipulating History/D. The Enchanted Forest

6 篇文章 0 订阅

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>bcbc>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 kn 时,最优解为选择连续区间和最大的。当 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 nk,则总增长-剩余=贡献

#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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值