Codeforces Round 900 (Div. 3)题解

 A - How Much Does Daytona Cost?

题意:给你一列数,问你是否存在一个子列使得子列中出现次数最多的数为k,显然只要k在序列中肯定可以做到

思路:find找一下序列中有没有出现k

B - Aleksa and Stack

题意:让你构造一列长度为n的数满足a[i-2]+a[i-1[!=3*a[i];

思路:其实容易发现连续的一列数肯定满足这个条件,所以直接输出一列长度为n的数即可

C - Vasilije in Cacak

题意:问你从1~n中取k个数,能不能让这个k个数的和等于x

思路:由于是在1~n中取,都是连续的,所以这个数只要在最小的k个数和最大的k个数之间即可(因为这样一定可以找到k个数使得他们的和等于x)

D - Reverse Madness

思路:差分维护每个位置的翻转次数,如果是奇数就翻转到对称位置,如果是偶数就不变

代码:

void solve()
{
    int n, k; // 每个区间记录翻转,如果翻转次数为奇数次就是对称的位置如果是偶数次就是原位置
    cin >> n >> k;
    string s;
    cin >> s;
    s = " " + s;
    vector l(k + 1), r(k + 1);
    for (int i = 1; i <= k; i++)
        cin >> l[i];
    for (int i = 1; i <= k; i++)
        cin >> r[i];
    int q;
    cin >> q;
    vector cnt(n + 1, 0);
    for (int i = 1; i <= q; i++)
    {
        int x;
        cin >> x;
        int pos = upper_bound(l.begin() + 1, l.end(), x) - l.begin() - 1; // 找到第一个大于他的数再前面一个就是他所在的区间
        int temp = min(x, l[pos] + r[pos] - x);
        cnt[temp]++; // 记录每个位置被翻转的次数
    }
    for (int i = 1; i <= k; i++)
    {
        int mid = (l[i] + r[i]) >> 1;
        int sum = 0;
        for (int j = l[i]; j <= mid; j++)
        {
            sum += cnt[j];
            if (sum & 1)
                swap(s[j], s[l[i] + r[i] - j]);
        }
    }
    // cout << s << endl;有空格
    for (int i = 1; i <= n; i++)
        cout << s[i];
    cout << endl;
}

你可能感兴趣的:(算法)