CF617E XOR and Favorite Number

CF617E XOR and Favorite Number

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

\(n,\ m\leq10^5,\ 0\leq a_i,\ k\leq10^6\)

莫队


重题 bzoj5301 [CQOI2018]异或序列

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

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

时间复杂度 \(O(n\sqrt 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\n", ans[i]);
  }
  return 0;
}
posted @ 2019-02-01 12:14  cnJuanzhang  阅读(247)  评论(0编辑  收藏  举报