BZOJ 4260: Codechef REBXOR( trie )

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

-----------------------------------------------------------------------

#include<cstdio>

#include<cstring>

#include<algorithm>

#include<cctype>

using namespace std;

const int maxn = 400009;

const int n = 31;

int read() {

char c = getchar(); int ret = 0;

for(; !isdigit(c); c = getchar());

for(; isdigit(c); c = getchar()) ret = ret * 10 + c - ‘0‘;

return ret;

}

int seq[maxn], L[maxn], R[maxn];

int N;

struct Node {

Node* ch[2];

} pool[maxn * n], *pt, *root;

void init() {

memset(pool, 0, sizeof pool);

pt = pool; root = pt++;

}

void Insert(int x) {

Node* t = root;

for(int i = n; i--; ) {

int v = (x >> i) & 1;

if(!t->ch[v]) t->ch[v] = pt++;

t = t->ch[v];

}

}

int Find(int x) {

Node* t = root;

int ret = 0;

for(int i = n; i--; ) {

int v = (((x >> i) & 1) ^ 1);

if(t->ch[v])

ret |= 1 << i, t = t->ch[v];

else

t = t->ch[v ^ 1];

}

return ret;

}

int main() {

N = read();

for(int i = 1; i <= N; i++) seq[i] = read();

int sum = L[0] = 0;

init(); Insert(sum);

for(int i = 1; i <= N; i++) {

sum ^= seq[i];

L[i] = max(L[i - 1], Find(sum));

Insert(sum);

}

sum = R[N + 1];

init(); Insert(sum);

for(int i = N; i; i--) {

sum ^= seq[i];

R[i] = max(R[i + 1], Find(sum));

Insert(sum);

}

int ans = 0;

for(int i = 1; i < N; i++)

ans = max(ans, L[i] + R[i + 1]);

printf("%d\n", ans);

return 0;

}

-----------------------------------------------------------------------

4260: Codechef REBXOR

Time Limit: 10 Sec  Memory Limit: 256 MB
Submit: 170  Solved: 76
[Submit][Status][Discuss]

Description

Input

输入数据的第一行包含一个整数N,表示数组中的元素个数。

第二行包含N个整数A1,A2,…,AN。

Output

输出一行包含给定表达式可能的最大值。

Sample Input

5
1 2 3 1 2

Sample Output

6

HINT

满足条件的(l1,r1,l2,r2)有:(1,2,3,3),(1,2,4,5),(3,3,4,5)。

对于100%的数据,2 ≤ N ≤ 4*105,0 ≤ Ai ≤ 109。

Source

By yts1999

时间: 2024-10-13 02:01:44

BZOJ 4260: Codechef REBXOR( trie )的相关文章

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

【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

【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();

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

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 3689 异或 Trie木+堆

标题效果:特定n的数量,这种需求n数22 XOR的值前者k少 首先,我们建立了一个二进制的所有数字Trie木,您可以使用Trie木size域检查出一些其他的数字XOR值首先k少 然后,我们要保持一个堆.其他XOR的整数值首先2增加堆(第一小是自己异或自己.不在题目要求范围内).当取出一个数异或值的第k小后,将第k+1小增加堆 一个异或值会被两个数分别取出一次.所以取出奇数次时输出,取2*k次就可以 时间复杂度O(nlogn) #include<cstdio> #include<cstri

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

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

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