bzoj 4888 [Tjoi2017]异或和 树状数组

本文介绍了一种使用二进制枚举和树状数组解决特定问题的方法,通过枚举二进制位,利用前缀和及树状数组统计满足条件的数对,最终求得目标值。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题面

题目传送门

解法

枚举最后的二进制位,假设是第\(k\)

问题就转化成有多少段和二进制意义下第\(k\)位是1

不妨转化成前缀和

变成有多少对\(i,j(i>j)\),使得\(s_i-s_j\)的第\(k\)位是1

我们可以枚举\(k\),假设\(s_i\)的第\(k\)位是1

如果\(s_i-s_j\)的第\(k\)位是1,那么存在两种情况:

1.\(s_j\)的第\(k\)位是0,且不存在减法退位这种情况

2.\(s_j\)的第\(k\)位是1,出现了减法退位

那么我们只要比较前\(k-1\)位的情况即可

用权值树状数组统计一下即可

\(s_i\)的第\(k\)位是0同理

那么只要开两个权值树状数组就可以解决问题

时间复杂度:\(O(n\ log^2\sum a_i)\)

代码

#include <bits/stdc++.h>
#define M 1000010
#define N 100010
using namespace std;
template <typename node> void read(node &x) {
    x = 0; int f = 1; char c = getchar();
    while (!isdigit(c)) {if (c == '-') f = -1; c = getchar();}
    while (isdigit(c)) x = x * 10 + c - '0', c = getchar(); x *= f;
}
int n, a[N], s[N], f[2][M];
int lowbit(int x) {return x & -x;}
void modify(int k, int x) {
    for (int i = x + 1; i <= s[n] + 1; i += lowbit(i))
        f[k][i]++;
}
int query(int k, int x) {
    int ret = 0;
    for (int i = x + 1; i; i -= lowbit(i))
        ret += f[k][i];
    return ret;
}
int calc(int l, int r, int k) {
    return query(k, r) - query(k, l);
}
int main() {
    int ans = 0; read(n);
    for (int i = 1; i <= n; i++)
        read(a[i]), s[i] = s[i - 1] + a[i];
    for (int k = 0; (1 << k) <= s[n]; k++) {
        int sum = 0, lim = (1 << k) - 1;
        for (int i = 0; i <= n; i++) {
            int t = (s[i] >> k) & 1, las = s[i] & lim;
            if (t) sum = (sum + calc(-1, las, 0) + calc(las, lim, 1)) % 2, modify(1, las);
                else sum = (sum + calc(-1, las, 1) + calc(las, lim, 0)) % 2, modify(0, las);
        } 
        if (sum) ans |= 1 << k;
        memset(f, 0, sizeof(f));
    }
    cout << ans << "\n";
    return 0;
}

转载于:https://www.cnblogs.com/copperoxide/p/9478376.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值