CF1511G Chips on a Board

不难发现这是个 Nim 游戏,于是对每对 \((L_i, R_i)\) 所求转化为:

\[\bigoplus_{i = 1}^n (a_i - L_i)[a_i \ge L_i] \]

暴力做时间复杂度就是 \(\mathcal O(n^2)\),考虑优化。

感觉好像可以倍增?设 \(f(i, k)\) 表示 \([i, i + 2^k)\)\(a_j - i\) 的异或和,然后再记一个 \(g(i, k)\) 表示 \([i, i + 2^k)\) 内棋子的个数就很妙地可以转移了。时间复杂度 \(\mathcal O(n \log n)\)

#include <bits/stdc++.h>

using namespace std;

constexpr int N = 2e5 + 10, K = 19;

int n, m, a[N], f[N][K], g[N][K];

int main() {
    ios_base::sync_with_stdio(0); cin.tie(nullptr), cout.tie(nullptr);
    cin >> n >> m;
    for (int i = 1; i <= n; i++) cin >> a[i], g[a[i]][0]++;
    for (int k = 1; k < K; k++) {
        for (int i = 1; i + (1 << k) - 1 <= m; i++) {
            g[i][k] = g[i][k - 1] + g[i + (1 << (k - 1))][k - 1];
            f[i][k] = f[i][k - 1] ^ f[i + (1 << (k - 1))][k - 1];
            if (g[i + (1 << (k - 1))][k - 1] & 1) f[i][k] ^= (1 << (k - 1));
        }
    }
    int q; cin >> q;
    while (q--) {
        int l, r; cin >> l >> r;
        int ans = 0, tmp = 0;
        for (int k = K - 1; k >= 0; k--) {
            if (l + (1 << k) - 1 <= r) {
                ans ^= f[l][k];
                if (g[l][k] & 1) ans ^= tmp;
                tmp ^= (1 << k);
                l += (1 << k);
            }
        }
        ans ? cout << 'A' : cout << 'B';
    }
    return 0;
}

作者:chy12321

出处:https://www.cnblogs.com/chy12321/p/17954696

版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。

posted @   Chy12321  阅读(7)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示
more_horiz
keyboard_arrow_up dark_mode palette
选择主题