[BZOJ3261] 最大异或和

mac2022-06-30  122

这题我借鉴了“主席树”的思想。

令v_i = x_1 ^ x_2 ^ ... ^ x_i 将v写成二进制,建立可持久化trie。

对于增加一个数,就相当于多开一个版本。

对于一个询问l,r,x,相当于求v_i ^ (v_N ^ x)最大(l - 1 <= i <= r - 1)。v_N ^ x是定值,于是贪心地找i就可以了。也就是对于一个v_N ^ x的二进制位是0则尽量在可持久化trie中找这位是1的。反之亦然。

实现的时候有个细节,就是可以在数列的最前面加一个0,这样方便处理。

时间复杂度O((N+M)*log 10^7) = O((N+M)*24) 空间复杂度大约为O((N+M)*24)

 (如果在IE浏览器下要拷代码的话复制到word里面就行了,虽然我也不知道为什么)

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 /**************************************************************      Problem: 3261      User: lazycal      Language: C++      Result: Accepted      Time:4436 ms      Memory:174244 kb ****************************************************************/   #include <cstdio> const int N = 600000 + 9; int root[N],v[N],Vc,num,t[25]; struct Tree {      int lc,rc,size; }tree[N*24]; inline void ten_to_two( int x, int (&t)[25]) {      t[0] = 0;      for (;x;x/=2) t[++t[0]] = x&1;      for ( int i = t[0] + 1;i <= 24; ++i) t[i] = 0; } inline void Add( int x) {      ++num;      v[num] = x^v[num - 1];      ten_to_two(v[num],t);      root[num] = Vc + 1;      int las = root[num - 1];      for ( int i = 24; i; --i) {          tree[++Vc] = tree[las]; ++tree[Vc].size;          if (t[i]) las = tree[las].rc, tree[Vc].rc = Vc + 1;          else las = tree[las].lc, tree[Vc].lc = Vc + 1;      }      tree[++Vc] = tree[las]; ++tree[Vc].size; } inline int zero_num( const int lt, const int rt) { return tree[tree[rt].lc].size - tree[tree[lt].lc].size;} inline int one_num( const int lt, const int rt) { return tree[tree[rt].rc].size - tree[tree[lt].rc].size;} int Query( int lt, int rt, int x)   {      ten_to_two(x,t);      int ans = 0;      for ( int i = 24; i; --i) {          if (t[i]) {              if (zero_num(lt,rt)) lt = tree[lt].lc,rt = tree[rt].lc;              else lt = tree[lt].rc,rt = tree[rt].rc,t[i] = 0;          } else {              if (one_num(lt,rt))  lt = tree[lt].rc,rt = tree[rt].rc,t[i] = 1;              else lt = tree[lt].lc,rt = tree[rt].lc;          }          if (t[i]) ans |= 1 << i-1;      }      return ans; } int main() {      int n,m;      scanf ( "%d%d" ,&n,&m);      root[0] = ++Vc;      Add(0);      for ( int i = 1,x; i <= n; ++i)          { scanf ( "%d" ,&x);Add(x);}      char c;      for ( int x,l,r;m--;) {          scanf ( "\n%c" ,&c);          if (c == 'A' ) { scanf ( "%d" ,&x);Add(x);}          else {              scanf ( "%d%d%d" ,&l,&r,&x);              printf ( "%d\n" ,Query(root[l - 1],root[r],x^v[num]));          }      } }

 

转载于:https://www.cnblogs.com/lazycal/p/3252994.html

相关资源:JAVA上百实例源码以及开源项目
最新回复(0)