zoukankan      html  css  js  c++  java
  • 【BZOJ2741】L-分块+可持久化trie

    测试地址:L
    做法:本题需要用到分块+可持久化trie。
    我们知道,一个连续异或和实际上就等于两个前缀异或和的异或,因此我们求出前缀异或和,转换成一个新的问题:求区间内两个数异或的最大值。这个东西直接用数据结构做不好做,而且又强制在线不能用莫队,因此考虑相似的分块。
    首先对序列分块,然后对于每一块,令mx(i,j)表示第i+1块左端点到点j区间中最大的两个数的异或值,显然这个可以用一个trie很快地做出来,时间复杂度为O(31nn)。接着对于每一个询问,如果这个询问的左右端点在同一块内,直接用trie暴力算出结果即可,时间复杂度为O(31n)。否则,这个区间就会被左端点所在块的右边界分割成两段,其中右边那段可以直接用前面算出的mx进行O(1)计算,而左边那段可以直接暴力O(31n)进行计算,关键是如何求出一个数在左边,一个数在右边的最大异或值呢?只需要对整个序列建一个可持久化trie,然后对于左边的每一个点,在可持久化trie对应的区间中贪心即可,时间复杂度为O(31n)
    于是我们就以O(31nn)的时间复杂度完成了这一题。
    以下是本人代码:

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    int n,m,blocksiz,a[12010],pre[12010],suf[12010],block[12010],totp,tot;
    int rt[12010]={0},nowrt[12010]={0},mx[120][12010]={0};
    int sum[400010]={0},ch[400010][2]={0};
    
    void insert(int v,int last,int x,bool mode)
    {
        sum[v]=sum[last]+1;
        for(int i=30;i>=0;i--)
        {
            bool f=(x&(1<<i));
            if (mode) ch[v][f]=++totp;
            else ch[v][f]=++tot;
            ch[v][!f]=ch[last][!f];
            v=ch[v][f];
            last=ch[last][f];
            sum[v]=sum[last]+1;
        }
    }
    
    int query(int v,int last,int x)
    {
        int ans=0;
        for(int i=30;i>=0;i--)
        {
            ans<<=1;
            bool f=(x&(1<<i));
            f=!f;
            if (sum[ch[v][f]]-sum[ch[last][f]]>0) ans++;
            else f=!f;
            v=ch[v][f];
            last=ch[last][f];
        }
        return ans;
    }
    
    void init()
    {
        totp=5000;
        for(int i=0;(i+1)*blocksiz<=n;i++)
        {
            tot=0;
            ch[1][0]=ch[1][1]=0;
            nowrt[(i+1)*blocksiz-1]=0;
            for(int j=(i+1)*blocksiz;j<=n;j++)
            {
                nowrt[j]=++tot;
                insert(nowrt[j],nowrt[j-1],suf[j],0);
                mx[i][j]=max(mx[i][j-1],query(nowrt[j],0,suf[j+1]));
            }
        }
        for(int i=1;i<=n;i++)
        {
            rt[i]=++totp;
            insert(rt[i],rt[i-1],pre[i],1);
        }
    }
    
    int solve(int L,int R)
    {
        int ans=0;
        if (block[L]==block[R])
        {
            tot=0;
            nowrt[L-1]=0;
            for(int i=L;i<=R;i++)
            {
                nowrt[i]=++tot;
                insert(nowrt[i],nowrt[i-1],suf[i],0);
                ans=max(ans,query(nowrt[i],0,suf[i+1]));
            }
        }
        else
        {
            ans=mx[block[L]][R];
            for(int i=L;i<(block[L]+1)*blocksiz;i++)
                ans=max(ans,query(rt[R],rt[(block[L]+1)*blocksiz-1],pre[i-1]));
            tot=0;
            nowrt[L-1]=0;
            for(int i=L;i<(block[L]+1)*blocksiz;i++)
            {
                nowrt[i]=++tot;
                insert(nowrt[i],nowrt[i-1],suf[i],0);
                ans=max(ans,query(nowrt[i],0,suf[i+1]));
            }
        }
        return ans;
    }
    
    int main()
    {
        scanf("%d%d",&n,&m);
        blocksiz=(int)sqrt(n)+1;
        pre[0]=0;
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            block[i]=i/blocksiz;
            pre[i]=pre[i-1]^a[i];
        }
        suf[n+1]=0;
        for(int i=n;i>=1;i--)
            suf[i]=suf[i+1]^a[i];
        init();
    
        int lastans=0;
        for(int i=1;i<=m;i++)
        {
            int x,y,l,r;
            scanf("%d%d",&x,&y);
            x=((ll)x+(ll)lastans)%(ll)n+1;
            y=((ll)y+(ll)lastans)%(ll)n+1;
            l=min(x,y),r=max(x,y);
            printf("%d
    ",lastans=solve(l,r));
        }
    
        return 0;
    }
  • 相关阅读:
    修改requests_html.AsyncHTMLSessions使得支持url参数
    MyBatis查询返回Map示例代码
    java.util.ConcurrentModificationException 异常原因和解决方法
    Springboot整合RabbitMQ(四)——设置消息过期时间TTL
    MySql Lock wait timeout exceeded该如何处理? (转载)
    对开发流程优化的建议
    容器未正常启动-->docker ps看不到,docker ps -a可以看到-->执行命令时出现Container is not running
    Linux下C语言多线程编程
    curl库相关使用
    PCB走线&过孔载流分析
  • 原文地址:https://www.cnblogs.com/Maxwei-wzj/p/9793262.html
Copyright © 2011-2022 走看看