【trie树】CF Edu12 E

Problem - E - Codeforces

题意:

思路:

这其实是一个套路题

区间异或转化成前缀异或,然后枚举 i 

对于每一个 i,ai ^ x = k,对 x 计数

先建一棵字典树,然后在字典树上计数

先去对 > k 的部分计数,再对 = k 的部分计数

如果 k 的第 j 位是1,那么沿着走就行,否则对 (k >> j & 1) ^ 1的部分计数,然后继续沿着走

最后的res += cnt[p]是对 = k 的部分计数

Code:

#include <bits/stdc++.h>

using i64 = long long;

constexpr int N = 1e6 + 10;
constexpr int M = 1e6 + 10;
constexpr int P = 2600;
constexpr i64 Inf = 1e18;
constexpr int mod = 1e9 + 7;
constexpr double eps = 1e-6;

int n, k;
int tot = 1;
int a[N], cnt[N * 30];
int tr[N * 30][2];

void insert(int x) {
    int p = 1;
    for (int j = 30; j >= 0; j --) {
        int u = (x >> j) & 1;
        if (!tr[p][u]) tr[p][u] = ++tot;
        p = tr[p][u];
        cnt[p] ++;
    }
}
i64 query(int x, int y) {
    int p = 1;
    i64 res = 0;
    for (int j = 30; j >= 0; j --) {
        int u = (x >> j) & 1, v = (y >> j) & 1;
        if (v) {
            p = tr[p][u ^ 1];
        }else {
            res += cnt[tr[p][u ^ 1]];
            p = tr[p][u];
        }
    }
    res += cnt[p];
    return res;
}
void solve() {
    std::cin >> n >> k;
    for (int i = 1; i <= n; i ++) std::cin >> a[i];
    for (int i = 1; i <= n; i ++) a[i] ^= a[i - 1];

    i64 ans = 0;
    for (int i = 1; i <= n; i ++) {
        insert(a[i - 1]);
        ans += query(a[i], k);
    }


    std::cout << ans << "\n";
}
signed main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    
    int t = 1;

    while (t--) {
        solve();
    }
    
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值