「十二省联考2019」异或粽子

Description

给出一个序列,定义一个区间的价值为的所有数的异或和,价值前大的区间的价值和

Solution

我们记表示前个数的异或和,那么一个区间的价值就是,然后考虑将插入到一个可持久化中,然后用堆维护每个所能得到的最大值,然后依次取出前项,每次取出后再在可持久化上面删掉一个数就好了

Code

 //Created Time:2020年05月10日 星期日 19时05分00秒
 #include <queue>
 #include <cstdio>
 #include <cstring>
 #include <iostream>
 #include <algorithm>
 #define uint unsigned int
 #define N 500005
 #define pi pair<uint, int>
 #define mkp make_pair
 #define fi first
 #define se second
 
 using namespace std;
 
 const int D = 31;
 
 int n, k;
 int rt[N];
 uint a[N];
 
 priority_queue<pi> Q;
 
 struct Trie{
  int cnt;
  int ch[N * 50][2], sz[N * 50];
 
  void upd(int las, int id, uint x, int w){
  int pre = rt[las], u = ++cnt; rt[id] = u;
  ch[u][0] = ch[pre][0];
  ch[u][1] = ch[pre][1];
  sz[u] = sz[pre] + w;
  for(int i = D; ~i; --i){
  int p = (x >> i) & 1, &v = ch[u][p];
  v = ++cnt; pre = ch[pre][p];
  ch[v][0] = ch[pre][0];
  ch[v][1] = ch[pre][1];
  sz[v] = sz[pre] + w;
  u = v;
  }
  return ;
  }
 
  uint find_max(int id, uint x){
  int u = rt[id]; uint res = 0;
  for(int i = D; ~i; --i){
  int p = (x >> i) & 1, v = ch[u][p ^ 1];
  if(sz[v]) u = v, res |= (1u << i);
  else if(!sz[ch[u][p]]) return 0;
  else u = ch[u][p];
  }
  return res;
  }
 }T;
 
 int main(){
 #ifndef ONLINE_JUDGE
     freopen("a.in", "r", stdin);
     freopen("a.out", "w", stdout);
 #endif
  scanf("%d%d", &n, &k); T.upd(0, 0, 0, 1);
  for(int i = 1; i <= n; ++i){
  scanf("%u", a + i), a[i] = a[i] ^ a[i - 1];
  T.upd(i - 1, i, a[i], 1); Q.push(mkp(T.find_max(i - 1, a[i]), i));
  }
  long long ans = 0;
  while(k){
  pi tmp = Q.top(); Q.pop();
  int id = tmp.se; --k;
  ans += tmp.fi; T.upd(id - 1, id - 1, tmp.fi ^ a[id], -1);
  Q.push(mkp(T.find_max(id - 1, a[id]), id));
  }
  cout << ans << endl;
  return 0;
 }



原文地址:https://www.cnblogs.com/roal-l/p/13086002.html