zoukankan      html  css  js  c++  java
  • bzoj 3261 最大异或和 可持久化字典树(01树)

    题目传送门

    思路:

      由异或的性质可得,题目要求的式子可以转化成求$max(pre[n]^x^pre[i])$,$pre[i]$表示前缀异或和,那么我们现在就要求出这个东西,所以用可持久化字典树来求,每次贪心的往相反的方向看是否有值,具体看代码即可,模板题,注意最好先插入一个0,查询区间的$(l,r)$也要注意一下端点,记住我们要的是前缀。

    #include<bits/stdc++.h>
    #define clr(a,b) memset(a,b,sizeof(a))
    typedef long long ll;
    using namespace std;
    const int maxn=600010;
    int sum[maxn*30],tr[maxn*30][2],cnt,root[maxn];
    int pre,n,m,l,r,d[30];
    void split(int x)
    {
        int len=0;
        while(x>0){
            d[len++]=x%2;
            x/=2;
        }
        while(len<27)d[len++]=0;
    }
    inline void update(int &rt,int las){
        sum[rt=++cnt]=sum[las]+1;
        int tmp=rt;
        for(int i=27;i>=0;i--){
            tr[tmp][d[i]^1]=tr[las][d[i]^1];
            tr[tmp][d[i]]=++cnt,las=tr[las][d[i]];
            sum[tmp=cnt]=sum[las]+1;        
        }
    }
    int query(int l,int r){
        int ans=0;
        for(int i=27;i>=0;i--)
        {
            if(sum[tr[r][d[i]^1]]-sum[tr[l][d[i]^1]]>0){
                ans|=(1<<i);
                r=tr[r][d[i]^1],l=tr[l][d[i]^1];
            }else{
                r=tr[r][d[i]],l=tr[l][d[i]];
            }
        }
        return ans;
    }
    int main(){
        while(cin>>n>>m)
        {
            pre=0;
            split(0);
            update(root[1],root[0]);
            n++;
            for(int i=2;i<=n;i++)
            {
                int x;
                scanf("%d",&x);
                pre^=x;
                split(pre);
                update(root[i],root[i-1]);
            }
            char op[10];
            for(int i=1;i<=m;i++)
            {
                scanf("%s",op);
                if(op[0]=='A'){
                    n++;
                    int x;
                    scanf("%d",&x);
                    pre^=x;
                    split(pre);
                    update(root[n],root[n-1]);
                }else{
                    int l,r,x;
                    scanf("%d%d%d",&l,&r,&x);
                    split(pre^x);
                    printf("%d
    ",query(root[l-1],root[r]));
                }
            }
        }
        
    }
    View Code
  • 相关阅读:
    .NET 回归
    Smart ORM v0.4.1开发计划
    计算4的1万次方的结果
    GMS Modem 短信收发组件
    计划任务的编成实现
    告别2007,展望2008
    Smart ORM v0.3发布(完全面向对象的轻量级ORM工具)
    Java中委托事件模型 (转)
    刚刚开通了博客,写点东西
    ASP.NET弹出对话框(转)
  • 原文地址:https://www.cnblogs.com/mountaink/p/10573677.html
Copyright © 2011-2022 走看看