zoukankan      html  css  js  c++  java
  • BZOJ3261:最大异或和——题解

    http://www.lydsy.com/JudgeOnline/problem.php?id=3261

    给定一个非负整数序列{a},初始长度为N。
    有M个操作,有以下两种操作类型:
    1、A x:添加操作,表示在序列末尾添加一个数x,序列的长度N+1。
    2、Q l r x:询问操作,你需要找到一个位置p,满足l<=p<=r,使得:a[p] xor a[p+1] xor ... xor a[N] xor x 最大,输出最大是多少。

    前置技能:HDU4825

    会了这个前置技能之后默认你会如何建trie跑贪心了。

    参考:https://www.cnblogs.com/y7070/p/5000471.html

    对于一段区间的异或和=r的前缀异或和^l-1的前缀异或和。

    所以我们处理出所有前缀异或和完后往trie上插。

    不过由于是区间询问,所以按照主席树(可持久化线段树)的想法,我们建立可持久化trie,具体的建立方法大致和主席树差不多,就不多讲了直接看代码吧。

    至于询问,我们直接询问哪个前缀能和(n的前缀异或和^x)异或值最大即可。

    直接引用参考博客:

    如果 x (询问数)的这一位为 p ,那么我们查询Sum[son[l][p ^ 1]] - Sum[son[r][p ^ 1],Sum为节点上有多少的值。

    如若 表达式 > 0 那么我们就像 p ^ 1 的方向行走,同时 答案加上 1 << d 因为这一位被我们错开了。

    否则只好向 p 的方向行走, 不加上 1 << d。

    原因请参考前置技能。

    另外还要注意我们查询的内容本身就是前缀和,左端点和右端点就需要同时减一,同时查区间,那么左端点就还需要需要减一

    参考里提到了一个小技巧就是在最开始插一个0,这样就不需要左端点和右端点同时减一了,不然自己看着怪难受的。

    #include<cstdio>
    #include<iostream>
    #include<queue>
    #include<cstring>
    #include<algorithm>
    #include<cctype>
    using namespace std;
    typedef long long ll;
    const int N=6e5+5;
    inline int read(){
        int X=0,w=0;char ch=0;
        while(!isdigit(ch)){w|=ch=='-';ch=getchar();}
        while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
        return w?-X:X;
    }
    inline char getc(){
        char ch=getchar();
        while(ch!='A'&&ch!='Q')ch=getchar();
        return ch;
    }
    struct node{
        int son[2],sum;
    }tr[50*N];
    int tot,b[N],rt[N],pool;
    void insert(int y,int &x,int k,int now){
        tr[x=++pool]=tr[y];
        tr[x].sum++;
        if(now<0)return;
        bool p=k&(1<<now);
        insert(tr[y].son[p],tr[x].son[p],k,now-1);
        return;
    }
    int query(int nl,int nr,int k,int now){
        if(now<0)return 0;
        bool p=k&(1<<now);
        int delta=tr[tr[nr].son[p^1]].sum-tr[tr[nl].son[p^1]].sum;
        if(delta>0)return (1<<now)+query(tr[nl].son[p^1],tr[nr].son[p^1],k,now-1);
        else return query(tr[nl].son[p],tr[nr].son[p],k,now-1);
    }
    int main(){
        int n=read()+1,m=read();
        for(int i=2;i<=n;i++)b[i]=b[i-1]^read();
        for(int i=1;i<=n;i++)insert(rt[i-1],rt[i],b[i],24);
        for(int i=1;i<=m;i++){
        char ch=getc();
        if(ch=='A'){
            b[++n]=b[n-1]^read();
            insert(rt[n-1],rt[n],b[n],24);
        }else{
            int l=read(),r=read(),x=read();
            printf("%d
    ",query(rt[l-1],rt[r],b[n]^x,24));
        }
        }
        return 0;
    }

    +++++++++++++++++++++++++++++++++++++++++++

     +本文作者:luyouqi233。               +

     +欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+

    +++++++++++++++++++++++++++++++++++++++++++

  • 相关阅读:
    五.Flink实时项目电商用户行为分析之订单支付实时监控
    四.Flink实时项目电商用户行为分析之恶意登录监控
    三.Flink实时项目电商用户行为分析之市场营销商业指标统计分析
    二.Flink实时项目电商用户行为之实时流量统计
    一.Flink实时项目电商用户行为分析之实时热门商品统计
    Flink 流处理API之实现UDF函数——更细粒度的控制流
    二.Flink 流处理API之Transform
    5组-Alpha冲刺-1/6
    5组 需求分析报告
    5组 团队展示
  • 原文地址:https://www.cnblogs.com/luyouqi233/p/8527581.html
Copyright © 2011-2022 走看看