7.20 希望渺茫

P11209 『STA - R8』小熊游景点 II

观察题目容易想到 01-trie,发现 \(a_i\)\(b_i\) 必然存在一起。

考虑插入每一位的情况,即 \((0, 0), (0, 1), (1, 0), (1, 1)\)

这样每个节点有可能有 \(4\) 个儿子,统计答案容易,但统计答案的过程可能是一棵二叉树,时间复杂度 \(\mathcal{O}(qn\log n)\)

我就这么做的

而对于 \(k\) 的某位,可以直接出答案的有 \((0, 1), (1, 1)\),分讨。而接下来访问的是 \((0, 0), (1, 1)\)\((1, 0), (0, 1)\),将两种情况合并成一点。查询形如一条链,时间复杂度 \(\mathcal{O}(q\log n)\)

别读了,退役吧

我不认为我不会这么简单的题,我同样不认为下次在考场上能应对类似的情况

一定要好好算时间复杂度。

code
const int N = 5e5 + 5;

int T, n, m, a[N], b[N], l;
int sz[N * 30][4], tot = 1, trie[N * 30][2];

void ins(int pos) {
  int p = 1;

  per(i, 29, 0) {
    int bita = a[pos] >> i & 1, bitb = b[pos] >> i & 1; sz[p][bita * 2 + bitb]++;
    if (!trie[p][bita ^ bitb]) trie[p][bita ^ bitb] = ++tot;
    p = trie[p][bita ^ bitb];
  }
}

int query(int k) {
  int p = 1, ans = 0;
  
  per(i, 29, 0) {
    int bit = k >> i & 1;
    if (i == 0) ans += sz[p][2 * bit] + sz[p][3 - 2 * bit];
    ans += sz[p][bit * 2 + 1];
    if (trie[p][bit]) p = trie[p][bit];
    else break;
  } 

  return ans;
}

int main() {
  read(T, n, m);
  rep(i, 1, n) read(a[i]);
  rep(i, 1, n) read(b[i]);
  rep(i, 1, n) ins(i);

  while (m--) {
    int k; read(k); k = k ^ (l * T);
    write(l = query(k), '\n');
  }
  return 0;
}
posted @ 2025-07-20 21:04  FRZ_29  阅读(10)  评论(0)    收藏  举报
2025-7-11 11:06:15 TOP-BOTTOM-THEME
Enable/Disable Transition
Copyright © 2023 ~ 2025 FRZ - 1801534592@qq.com
Illustration from たとえ,by Rella