CF617E XOR and Favorite Number

CF617E XOR and Favorite Number

已知一个序列 (a_1, a_2, cdots, a_n)(k)(m) 次询问给出 (l, r) ,求 (displaystylesum_{i=l}^rsum_{j=i}^r[a_xoplus a_{x+1}oplus cdots oplus a_y=k])

(n, mleq10^5, 0leq a_i, kleq10^6)

莫队


重题 bzoj5301 [CQOI2018]异或序列

考虑维护一个异或前缀和,问题就转化为了:区间 ([l-1, r]) 中,有多少对数异或和为 (k)。莫队开桶记录即可

注意数组空间大小以及 (long long)

时间复杂度 (O(nsqrt n))

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
const int maxn = 1e5 + 10;
int n, m, k, sz, a[maxn], bl[maxn], cnt[maxn * 20]; ll now, ans[maxn];
struct node {
  int l, r, tid;
  bool operator < (const node& o) const {
    return bl[l] != bl[o.l] ? l < o.l : r > o.r;
  }
} q[maxn];

void add(int x) { now += cnt[x ^ k], cnt[x]++; }
void del(int x) { cnt[x]--, now -= cnt[x ^ k]; }

int main() {
  scanf("%d %d %d", &n, &m, &k), sz = sqrt(n);
  for (int i = 1; i <= n; i++) {
    scanf("%d", a + i), a[i] ^= a[i - 1], bl[i] = (i - 1) / sz + 1;
  }
  for (int i = 1; i <= m; i++) {
    scanf("%d %d", &q[i].l, &q[i].r), q[i].l--, q[i].tid = i;
  }
  sort(q + 1, q + m + 1);
  int l = 0, r = -1;
  for (int i = 1; i <= m; i++) {
    while (q[i].l < l) add(a[--l]);
    while (q[i].r > r) add(a[++r]);
    while (q[i].l > l) del(a[l++]);
    while (q[i].r < r) del(a[r--]);
    ans[q[i].tid] = now;
  }
  for (int i = 1; i <= m; i++) {
    printf("%I64d
", ans[i]);
  }
  return 0;
}
原文地址:https://www.cnblogs.com/Juanzhang/p/10345401.html