2025.3.22 Codeforces Round 1011 (Div. 2)
Solved: 5/7
Rank(trusted): 15
Rank(all): 46
A. Serval and String Theory
题意:给一个字符串,可以交换两个字符至多 \(k\) 次,问能否使它的字典序严格大于它的反串的字典序。
如果已经满足条件,直接输出 YES 即可;如果所有字符相等,直接输出 NO 即可。其他情况只需交换一次。
bool solve(){
    int n, k; cin >> n >> k;
    string a; cin >> a;
    bool flag = 0;
    for (int i=0; i<n; ++i)
    {
        if (a[i] != a[0]) flag = 1;
    }
    if (!flag) return 0;
    for (int i=0; i<n-i-1; ++i)
    {
        if (a[i] < a[n-i-1]) return 1;
        if (a[i] > a[n-i-1])
        {
            if (k) return 1;
            else return 0;
        }
    }
    if (k) return 1;
    else return 0;
}
B. Serval and Final MEX
题意:给一个序列,每次可选择一个长度 \(>1\) 的连续子序列将其替换为 mex,问能否将整个序列变成只有一个 0。给出操作方案(不要求操作数最少)。序列长度 \(\geq 4\)(这保证了有解)。
将序列每两个数分成一组(若长度为奇数则最后三个分成一组),如果组内有 0 则取 mex,组内没有 0 则不变。这样做完一轮操作后序列所有数都不为 0。此时再对整个序列取 mex 即可。
void solve(){
    int n, m=0; cin >> n;
    vector<int> a(n); cin >> a;
    vector<pii> ans;
    for (int i=0; i<n-1; i+=2)
    {
        if (i != n-3)
        {
            if (!a[i] || !a[i+1]) ans.push_back(pii(i-m,i+1-m)), ++m;
        }
        else
        {
            if (!a[i] || !a[i+1] || !a[i+2]) ans.push_back(pii(i-m,i+2-m)), m+=2;
        }
    }
    ans.push_back(pii(0,n-m-1));
    cout << ans.size() << '\n';
    for (int i=0; i<ans.size(); ++i) cout << ans[i].first+1 << ' ' <<ans[i].second+1 << "\n";
}
C. Serval and The Formula
题意:给两个数 \(x,y\),找 \(k>0\) 使得 \((x+k)\oplus (y+k) = (x+k) + (y+k)\)。
实际上就是让 \(x+k\) 和 \(y+k\) 的二进制表示中不出现对应都等于 1 的位。不妨设 \(x>y\),只需令 \(x\) 变为大于 \(x\) 且最小的 \(2\) 的幂次即可。此时 \(x\) 的最高位是 1 后面是 0,\(y\) 的位数小于 \(x\),必然满足条件。
void solve(){
    ll x, y; cin >> x >> y;
    if (x == y)
    {
        cout << "-1\n";
        return;
    }
    if (x<y) swap(x, y);
    cout << (1ll << (__lg(x) + 1)) - x << "\n";
}
D. Serval and Kaitenzushi Buffet
题意:有 \(n\) 个物品,第 \(i\) 个物品的价值是 \(d_i\),这些物品会依次到来。每次你可以选择拿走这个物品并令 \(r\leftarrow r+k\),也可以不拿这个物品并令 \(r\leftarrow \max\{0,r-1\}\)。需要保证最后 \(r=0\)。求拿走的物品的价值之和的最大值。
从后往前考虑,则问题变成不拿物品可以让 \(r\) 加一,拿一个物品可以让 \(k\) 减 \(k\) 但不能减到负数。此外还可以无条件用前面的物品替换后面的物品。用一个堆来维护这个过程。
void solve(){
    int n, k; cin >> n >> k;
    vector <int> a(n); cin >> a;
    int r = 0;
    ll ans = 0;
    priority_queue <int> pq;
    for (int i=n-1; i>=0; --i)
    {
        if (r >= k)
        {
            pq.push(-a[i]);
            ans += a[i];
            r -= k;
        }
        else if (!pq.empty() && -pq.top() < a[i])
        {
            pq.push(-a[i]);
            ans += a[i] + pq.top();
            pq.pop();
            ++r;
        }
        else ++r;
    }
    cout << ans << "\n";
}
E. Serval and Modulo
题意:给两个序列 \(a\) 和 \(b\),已知 \(b\) 是 \(a\) 的每个元素模 \(k\) 再随机打乱得到的,求一个合法的 \(k\)。
注意到随机打乱后总和是不变的,而 \(k\) 一定是 \(S = \sum a_i - \sum b_i\) 的因子,所以枚举 \(S\) 的全部因子暴力检查即可。注意判无解。
ll solve(){
    int n, m=0; cin >> n;
    vector <int> a(n), b(n);
    cin >> a >> b;
    sort(all(a)), sort(all(b));
    ll sum = 0;
    for (int i=0; i<n; ++i)
    {
        if (a[i] < b[i]) return -1;
        sum += a[i]-b[i];
        m = max(m, b[i]);
    }
    if (!sum) return m+1;
    vector<int> c(n);
    auto check = [&](ll u) -> bool
    {
        for (int i=0; i<n; ++i) c[i] = a[i] % u;
        sort(all(c));
        for (int i=0; i<n; ++i) if (c[i] != b[i]) return 0;
        return 1;
    };
    for (ll i=1; i*i<=sum; ++i) if (!(sum%i))
    {
        if (i > m && check(i)) return i;
        if (sum/i > m && check(sum/i)) return sum/i;
    }
    return -1;
}

 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号