[十二省联考2019] 异或粽子

[十二省联考2019] 异或粽子

第一次写 \(01\ Trie\) 诶.

这道题还是比较简单的, 毕竟我这种屑都能写出来.

题目要求前 \(k\) 大的区间异或和. 由于异或的性质, 我们将原数列做一个前缀异或和, 于是题目就转换成了选出 \(k\)\((i, j), i \le j\) , 使 \(sum[i]\ xor\ sum[j]\) 最大, 然后由于这个 \(l \le r\) 的限制比较烦人, 并且 \(k \le \frac{n(n - 1)}{2}\) , 所以我们就可以转化成前 \(2k\) 大的, 不要求 \(l \le r\) . 最后再 \(/ 2\) 就是了.

然后将这个 \(n + 1\) 个前缀异或和 (包括 \(0\) ) 插入一个 \(01\ Trie\) , 就能在 \(O(\log a)\) 的时间内求出异或 \(s[i]\) 最大的 \(s[j]\) . 我们先把最大的 \(n + 1\) 组插入一个大根堆, 然后每次取出堆顶, 再插入堆顶的下一位, 共取出 \(2k\) 次.

复杂度 \(O(2k \log a)\)

\(code:\)

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;

ll read() {
  ll x = 0, f = 1;
  char ch = getchar();
  for (; !isdigit(ch); ch = getchar()) if (ch == '-') f = -1;
  for (; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + (ch ^ 48);
  return x * f;
}

const int N = 2e7 + 5;

struct Trie {
  int ch[N][2], sz[N], cnt;
  void Insert(ll v) {
    int x = 0;
    for (int i = 33; i >= 0; i--) {
      int y = (v >> i) & 1;
      if (!ch[x][y]) ch[x][y] = ++cnt;
      x = ch[x][y];
      sz[x]++;
    }
  }
  ll Query(ll v, int k) {
    int x = 0;
    ll ans = 0;
    for (int i = 33; i >= 0; i--) {
      int y = (v >> i) & 1;
      if (k <= sz[ch[x][y ^ 1]]) {
        x = ch[x][y ^ 1], ans |= 1ll << i;
      }
      else k -= sz[ch[x][y ^ 1]], x = ch[x][y];
    }
    return ans;
  }
} t;

struct Node {
  int id, rk;
  ll val;
  bool operator < (const Node &a) const {
    return a.val > val;
  }
};

int n, k;
ll a[N], ans;
priority_queue <Node> q;

int main() {
  n = read(), k = read() << 1;
  for (int i = 1; i <= n; i++) a[i] = a[i - 1] ^ read();
  for (int i = 0; i <= n; i++) t.Insert(a[i]);
  Node x;
  for (int i = 0; i <= n; i++) {
    x.id = i, x.rk = 1, x.val = t.Query(a[i], 1);
    q.push(x);
  }
  for (int i = 1; i <= k; i++) {
    x = q.top(); q.pop();
    ans += x.val;
    if (x.rk <= n) {
      x.rk++, x.val = t.Query(a[x.id], x.rk);
      q.push(x);
    }
  }
  printf("%lld", ans >> 1);
  return 0;
}
posted @ 2021-09-26 14:27  sshadows  阅读(22)  评论(1编辑  收藏  举报