bzoj 4260: Codechef REBXOR

Description

Solution

记录前缀答案和后缀答案,然后枚举断点合并即可
求出以每一个结尾的最大异或的段,相当于求两个前缀异或值的最大值,用trie树贪心即可

#include<bits/stdc++.h>
using namespace std;
const int N=400005;
int n,a[N],f[N],bin[N],rt=0,ch[N*30][2],cnt=0;
inline int qry(int x,int d,int v){
  if(d==-1)return 0;
  if(v&bin[d]){
    if(ch[x][0])return qry(ch[x][0],d-1,v)|bin[d];
    return qry(ch[x][1],d-1,v);
  }
  else{
    if(ch[x][1])return qry(ch[x][1],d-1,v)|bin[d];
    return qry(ch[x][0],d-1,v);
  }
}
inline void ins(int &x,int d,int v){
  if(!x)x=++cnt;
  if(d==-1)return ;
  ins(ch[x][(v&bin[d])>0],d-1,v);
}
int main(){
  freopen("pp.in","r",stdin);
  freopen("pp.out","w",stdout);
  scanf("%d",&n);
  for(int i=1;i<=n;i++)scanf("%d",&a[i]);
  bin[0]=1;for(int i=1;i<=30;i++)bin[i]=bin[i-1]<<1;
  int sum=0,ans=0;
  ins(rt,30,0);
  for(int i=1;i<=n;i++){
    sum^=a[i];
    f[i]=max(f[i-1],qry(rt,30,sum));
    ins(rt,30,sum);
  }
  sum=0;rt=0;cnt=0;
  memset(ch,0,sizeof(ch));
  ins(rt,30,0);
  for(int i=n;i>=2;i--){
    sum^=a[i];
    ans=max(ans,f[i-1]+qry(rt,30,sum));
    ins(rt,30,sum);
  }
  printf("%d\n",ans);
  return 0;
}

原文地址:https://www.cnblogs.com/Yuzao/p/8408590.html

时间: 2024-10-08 13:59:14

bzoj 4260: Codechef REBXOR的相关文章

BZOJ 4260: Codechef REBXOR( trie )

求出前缀和, 那么以第x个元素结尾的最大异或值是max(sumx^sump)(1≤p<x), 用trie加速. 后缀同理, 然后扫一遍就OK了.时间复杂度O(31N) ----------------------------------------------------------------------- #include<cstdio> #include<cstring> #include<algorithm> #include<cctype>

bzoj4260: Codechef REBXOR

求异或maxmin一般用trie (二进制式的trie).query中找的是满足((x>>i)&1)^A=1,那么A=((x>>i)&1)^1:maxx=max(sumx,sumi)(i=[1,x]).(YY一下异或的性质 #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #def

【BZOJ4260】 Codechef REBXOR 可持久化Trie

看到异或就去想前缀和(⊙o⊙) 这个就是正反做一遍最大异或和更新答案 最大异或就是很经典的可持久化Trie,从高到低贪心 WA: val&(1<<(base-1))得到的并不直接是1/0 1 #include<bits/stdc++.h> 2 #define ll long long 3 #define N 400005 4 using namespace std; 5 inline int read(){ 6 int x=0,f=1;char ch=getchar();

BZOJ 4260 REBXOR

TMD我怎么卡了这么久的常啊.... 就枚举分割点,左手一颗trie,右手一颗trie,就好了. #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define maxn 400050 using namespace std; int n,a[maxn],x[maxn],root,ls[maxn*32],rs[maxn*32],tot=0; int mx[ma

BZOJ 3514: Codechef MARCH14 GERALD07加强版

3514: Codechef MARCH14 GERALD07加强版 Time Limit: 60 Sec  Memory Limit: 256 MBSubmit: 1356  Solved: 514[Submit][Status][Discuss] Description N个点M条边的无向图,询问保留图中编号在[l,r]的边的时候图中的联通块个数. Input 第一行四个整数N.M.K.type,代表点数.边数.询问数以及询问是否加密.接下来M行,代表图中的每条边.接下来K行,每行两个整数L

BZOJ 3514: Codechef MARCH14 GERALD07加强版( LCT + 主席树 )

从左到右加边, 假如+的边e形成环, 那么记下这个环上最早加入的边_e, 当且仅当询问区间的左端点> _e加入的时间, e对答案有贡献(脑补一下). 然后一开始是N个连通块, 假如有x条边有贡献, 答案就是N-x. 用LCT维护加边, 可持久化线段树维护询问. O(NlogN) ------------------------------------------------------------------------------------ #include<cstdio> #inc

bzoj 4260

设a[i]为前缀和,则i~j的异或和为a[j]^a[i],对于2个只需把另一个当成后缀就可以了 求max(a[j]^a[i])的话就用tire维护就可以了 1 #include<bits/stdc++.h> 2 #define inc(i,l,r) for(int i=l;i<=r;i++) 3 #define dec(i,l,r) for(int i=l;i>=r;i--) 4 #define link(x) for(edge *j=h[x];j;j=j->next) 5

BZOJ4260 Codechef REBXOR 题解

题目大意: 给定一个长度为n的序列,求1≤l1≤r1<l2≤r2≤n使得(⊕r1i=l1ai)+(⊕r2i=l2ai)最大,输出这个最大值. 思路: 用Trie求出前缀异或和以及后缀异或和,再求出前缀异或和以及后缀异或和中最大的,前后相加,求最大值.用可持久化Trie求异或和也可. 代码: Trie 1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #define M 400009 5 us

【bzoj4260】Codechef REBXOR Trie树

题目描述 输入 输入数据的第一行包含一个整数N,表示数组中的元素个数. 第二行包含N个整数A1,A2,…,AN. 输出 输出一行包含给定表达式可能的最大值. 样例输入 5 1 2 3 1 2 样例输出 6 题解 Trie树 还是本着100000(2)>011111(2)的原则,显然需要从高位贪心取值. 又因为x^x=0,所以有$a_l\oplus a_{l+1}\oplus \cdots\oplus a_{r-1}\oplus a_r=(a_1\oplus a_2\oplus\cdots\opl