zoukankan      html  css  js  c++  java
  • [BZOJ3261]最大异或和

    题目大意:

    给定一个非负整数序列{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 最大,输出最大是多少。

    解题思路:

    首先,a[1] xor a[2] xor ... xor a[N] xor x很容易求出。

    然后,异或满足交换律和结合律。

    此处询问的是后缀,我们考虑转化成前缀异或。

    设s[i]表示a[1] xor a[2] xor ... xor a[i]

    即在([l-1,r-1])中找一个数p,使s[N] xor x xor s[p]最大。

    用可持久化Trie维护前缀异或信息,和节点个数,然后在区间内进行前缀差查询(可持久化Trie满足可加性),每次贪心地使高位尽可能大即可。

    于是长得和主席树差不多。

    毒瘤数据结构大法好o((⊙﹏⊙))o

    C++ Code:

    #include<bits/stdc++.h>
    int n,m,s[600006],b[25],cnt=0,ans,rt[600006];
    struct node{
        int ch[2],c;
    }d[22000006];
    void add(int&o,int&pr,int nw){
        o=++cnt;
        if(!~nw){d[o].c=d[pr].c+1;return;}
        d[o].ch[0]=d[pr].ch[0];
        d[o].ch[1]=d[pr].ch[1];
        add(d[o].ch[b[nw]],d[pr].ch[b[nw]],nw-1);
        d[o].c=d[d[o].ch[0]].c+d[d[o].ch[1]].c;
    }
    void ask(int&R,int&L,int nw){
        if(!~nw)return;
        int _1=b[nw]^1;
        if(d[d[R].ch[_1]].c>d[d[L].ch[_1]].c){
            ans|=1<<nw;
            ask(d[R].ch[_1],d[L].ch[_1],nw-1);
        }else
        ask(d[R].ch[b[nw]],d[L].ch[b[nw]],nw-1);
    }
    inline int readint(){
        int c=getchar(),d=0;
        for(;!isdigit(c);c=getchar());
        for(;isdigit(c);c=getchar())
        d=(d<<3)+(d<<1)+(c^'0');
        return d;
    }
    int main(){
        n=readint(),m=readint();
        s[0]=0;
        for(int i=1;i<=n;++i){
            int q=readint();
            s[i]=s[i-1]^q;
            for(int j=24;~j;--j)
            b[j]=(s[i]>>j)&1;
            add(rt[i],rt[i-1],24);
        }
        while(m--){
            char c[2];
            scanf("%s",c);
            if(c[0]=='A'){
                int q=readint();
                ++n;
                s[n]=s[n-1]^q;
                for(int j=24;~j;--j)
                b[j]=(s[n]>>j)&1;
                add(rt[n],rt[n-1],24);
            }else{
                ans=0;
                int l=readint(),r=readint(),x=readint(),p;
                p=s[n]^x;
                if(r==1){
                    printf("%d
    ",p);
                    continue;
                }
                for(int j=24;~j;--j)
                b[j]=(p>>j)&1;
                ask(rt[r-1],l-2>0?rt[l-2]:rt[0],24);
                printf("%d
    ",ans);
            }
        }
        return 0;
    }
  • 相关阅读:
    HDU4474 Yet Another Multiple Problem BFS搜索
    HDU4473 Exam 数学分析
    2013ACM多校联合(4)
    POJ1273 网络流...
    HDU4472 Count 递推
    POJ1149 PIGS 网络流
    UVA10881 Piotr's Ants 想法题
    javascript js string.Format()收集
    修改 设置 vs.net 网站 调试 设为 起始页
    【转】HTML5杂谈 概念与现行游戏 割绳子 宝石迷阵
  • 原文地址:https://www.cnblogs.com/Mrsrz/p/9385594.html
Copyright © 2011-2022 走看看