• BZOJ 3261 最大异或和 可持久化Trie树


    题目大意:给定一个序列,提供下列操作:

    1.在数组结尾插入一个数

    2.给定l,r,x,求一个l<=p<=r,使x^a[p]^a[p+1]^...^a[n]最大

    首先我们能够维护前缀和 然后就是使x^sum[n]^sum[p-1]最大

    x^sum[n]为定值,于是用Trie树贪心就可以

    考虑到l-1<=p-1<=r-1,我们不能对于每一个询问都建一棵Trie树,可是我们能够对于Trie数维护前缀和,建立可持久化Trie树

    每一个区间[l,r]的Trie树为tree[r]-tree[l-1]

    注意0要插入一个数字0。所以把-1作为空节点。然后把数组向前推进一位就可以

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define M 600600
    using namespace std;
    struct Trie{
        int cnt;
        Trie *son[2];
    }*tree[M],node[14000000];
    int n,m,tot,sum[M];
    inline int getc() {
        static const int L = 1 << 15;
        static char buf[L], *S = buf, *T = buf;
        if (S == T) {
            T = (S = buf) + fread(buf, 1, L, stdin);
            if (S == T)
                return EOF;
        }
        return *S++;
    }
    inline int getint() {
        int c;
        while(!isdigit(c = getc()));
        int tmp = c - '0';
        while(isdigit(c = getc()))
            tmp = (tmp << 1) + (tmp << 3) + c - '0';
        return tmp;
    }
    inline int getch() {
        int c;
        while((c = getc()) != 'A' && c != 'Q');
        return c;
    }
    inline Trie* New_Node(int _,Trie*__,Trie*___)
    {
        node[tot].cnt=_;
        node[tot].son[0]=__;
        node[tot].son[1]=___;
        return &node[tot++];
    }
    Trie* Build_Tree(Trie *p,int x,int pos)
    {
        if(!pos)
            return New_Node(p->cnt+1,tree[0],tree[0]);
        if( (x&pos)==0 )
            return New_Node(p->cnt+1,Build_Tree(p->son[0],x,pos>>1),p->son[1]);
        else
            return New_Node(p->cnt+1,p->son[0],Build_Tree(p->son[1],x,pos>>1));
    }
    int Get_Ans(Trie *l,Trie *r,int x,int pos)
    {
        int num=x&pos?

    1:0; if(!pos) return 0; if(r->son[!num]->cnt-l->son[!num]->cnt) return pos + Get_Ans(l->son[!num],r->son[!num],x,pos>>1); else return Get_Ans(l->son[num],r->son[num],x,pos>>1); } int main() { int i,x,l,r; char p[10]; tree[0]=New_Node(0,0x0,0x0); tree[0]->son[0]=tree[0]->son[1]=tree[0]; tree[1]=Build_Tree(tree[0],0,1<<25); cin>>n>>m; for(i=1;i<=n;i++) { x=getint(); sum[i]=sum[i-1]^x; tree[i+1]=Build_Tree(tree[i],sum[i],1<<25); } for(i=1;i<=m;i++) { p[0]=getch(); if(p[0]=='A') { x=getint(); sum[n+1]=sum[n]^x; tree[n+2]=Build_Tree(tree[n+1],sum[n+1],1<<25); ++n; } else { l=getint(); r=getint(); x=getint(); x^=sum[n];--l;--r; printf("%d ", Get_Ans(tree[l],tree[r+1],x,1<<25) ); } } }



  • 相关阅读:
    Spring 框架的概述以及Spring中基于XML的IOC配置
    SpringBoot(1)
    C/C++经典程序之打印三角形
    C++构造函数详解(复制构造函数)
    利用函数模板计算并返回数组d 中size个元素的平方和
    C++模板之typename和class关键字的区别
    构造函数与成员函数的区别?
    为什么多数穷人很难逆袭成功
    用递归方式求解这个问题:一只母兔从四岁开始每年生一只小母兔,按此规律,第n年有多少只母兔?
    编写一个函数 reverseDigit(int num).该函数读入一个整数,然后将这个整数的每个位上的数字逆序输出。
  • 原文地址:https://www.cnblogs.com/blfbuaa/p/6739834.html
Copyright © 2020-2023  润新知