BZOJ2741 【FOTILE模拟赛】L

题目描述:

对于一个询问,你需要求出max(Ai xor Ai+1 xor Ai+2 ... xor Aj),其中l<=i<=j<=r。(强制在线)

题解:

可持久化Trie+分块。

分块处理当前块上某点为起点,块后任一点为终点的最大异或和。

代码:

#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define N 12050
#define M 6050
inline int rd()
{
    int f=1,c=0;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){c=10*c+ch-'0';ch=getchar();}
    return f*c;
}
int n,m,a[N],rt[N],ans=0,wt;
struct Trie
{
    int tot,siz[35*N],ch[35*N][2];
    int insert(int now,int x)
    {
        int u,ret,f=rt[now-1];
        u=ret=++tot;
        for(int i=30;i>=0;i--)
        {
            ch[u][0]=ch[f][0],ch[u][1]=ch[f][1],siz[u]=siz[f]+1;
            int c = (x>>i)&1;
            ch[u][c]=++tot;
            u=ch[u][c],f=ch[f][c];
        }
        siz[u]=siz[f]+1;
        return ret;
    }
    int query(int l,int r,int x)
    {
        l=rt[l],r=rt[r];
        int ret = 0;
        for(int i=30;i>=0;i--)
        {
            int c = (x>>i)&1;
            if(siz[ch[r][!c]]-siz[ch[l][!c]])
            {
                ret|=(1<<i);
                l=ch[l][!c],r=ch[r][!c];
            }else l=ch[l][c],r=ch[r][c];
        }
        return ret;
    }
}tr;
int f[N][150],bel[N];
int main()
{
    n=rd()+1,m=rd();
    rt[1]=tr.insert(1,0);
    for(int i=2;i<=n;i++)
    {
        a[i]=rd()^a[i-1];
        rt[i]=tr.insert(i,a[i]);
    }
    wt=(int)sqrt(n);
    for(int i=1;i<=n;i++)
        bel[i]=(i-1)/wt;
    for(int j=0;j<=(n-1)/wt;j++)
    {
        int l = j*wt,r = min((j+1)*wt,n);
        for(int i=l+1;i<=n;i++)
        {
            f[i][j]=max(f[i-1][j],tr.query(l,r,a[i]));
        }
    }
    while(m--)
    {
        int l=(int)((1ll*rd()+1ll*ans)%(n-1)+1);
        int r=(int)((1ll*rd()+1ll*ans)%(n-1)+1);
        if(l>r)swap(l,r);
        ans=0;
        r++;
        if(bel[l]==bel[r])
        {
            for(int i=l;i<=r;i++)
                ans=max(ans,tr.query(l-1,r,a[i]));
        }else
        {
            for(int i=l;bel[i]==bel[l];i++)
                ans=max(ans,tr.query(l-1,r,a[i]));
            for(int i=r;bel[i]==bel[r];i--)
                ans=max(ans,tr.query(l-1,r,a[i]));
            for(int i=bel[l]+1;i<bel[r];i++)
                ans=max(ans,f[r][i]);
        }
        printf("%d\n",ans);
    }

    return 0;
}

 

posted @ 2018-11-30 20:33  LiGuanlin  阅读(124)  评论(0编辑  收藏  举报