B4260 Codechef REBXOR

真是6块钱cpu(笑

爆炸入口

踹树练习(汗

对于二进制异或和弹性,我们可以贪心的来做。

瓶颈在于快速贪心。

我们可以维护一个trie树,储存异或前缀和。每次在trie树上贪心的跑。

正向and反向跑一次,就可以了

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int manx=4e+5;
int t[manx<<5][2],tail;
int l[manx],r[manx],a[manx];
void ins(int val)
{
    int now=0;
    for(int i=1<<30;i;i>>=1)
    {
        int c=(val&i) ? 1 : 0 ;
        if(!t[now][c])  t[now][c]=++tail;
        now=t[now][c];
    }
    return ;
}//插入
int find(int val)
{
    int now=0,ans=0;
    for(int i=1<<30;i;i>>=1)
    {
        int c=(val&i) ? 1 : 0;
        if(t[now][c^1]) now=t[now][c^1],ans+=i;//每次根据二进制位,贪心的选择路径
        else    now=t[now][c];
    }
    return ans;
}
int main()
{
    int n;
    scanf("%d",&n);
    int now=0;ins(0);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        now^=a[i];
        ins(now);
        l[i]=max(l[i-1],find(now));
    }//正向扫一遍
    memset(t,0,sizeof(t));now=0,tail=0;ins(0);
    for(int i=n;i>=1;i--)
    {
        now^=a[i];
        ins(now);
        r[i]=max(r[i+1],find(now));//反向和一遍
    }
    int ans=-0x7fffffff;
    for(int i=1;i<=n;i++)
        ans=max(l[i]+r[i+1],ans);//这里我们只需要保证不香蕉就可以了(汗
    printf("%d",ans);
}

原文地址:https://www.cnblogs.com/Lance1ot/p/9221761.html

时间: 2024-11-09 00:09:13

B4260 Codechef REBXOR的相关文章

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: 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 题解

题目大意: 给定一个长度为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

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

【trie树专题】

[map || trie]P2580 于是他错误的点名开始了 题目背景 XS中学化学竞赛组教练是一个酷爱炉石的人. 他会一边搓炉石一边点名以至于有一天他连续点到了某个同学两次,然后正好被路过的校长发现了然后就是一顿欧拉欧拉欧拉(详情请见已结束比赛CON900). 题目描述 这之后校长任命你为特派探员,每天记录他的点名.校长会提供化学竞赛学生的人数和名单,而你需要告诉校长他有没有点错名.(为什么不直接不让他玩炉石.) 输入格式 第一行一个整数 n,表示班上人数.接下来 n 行,每行一个字符串表示其

CodeChef FNCS (分块+树状数组)

题目:https://www.codechef.com/problems/FNCS 题解: 我们知道要求区间和的时候,我们用前缀和去优化.这里也是一样,我们要求第 l 个函数到第 r 个函数 [l, r] 的函数和,那么我们可以用 sum[r] - sum[l-1] 来求得. 由于这个数据量有点大,所以我们将函数分块. 例如样例: 1 3 有5个函数,那么我们分成3块.{ [1 3] , [2 5] }, { [4 5], [3 5] }, { [1 2] }.每一块对应都有一个sum ,这时如

codechef营养题 第三弹

第三弾が始まる! codechef problems 第三弹 一.Motorbike Racing 题面 It's time for the annual exciting Motorbike Race in Byteland. There are N motorcyclists taking part in the competition. Johnny is watching the race. At the present moment (time 0), Johnny has taken