欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【GDOI2018模拟9.21】数列

程序员文章站 2022-06-23 10:49:34
...

(File IO): input:sequence.in output:sequence.out
Time Limits: 2000 ms Memory Limits: 262144 KB Detailed Limits

Description

【GDOI2018模拟9.21】数列

Input

【GDOI2018模拟9.21】数列

Output

【GDOI2018模拟9.21】数列

Sample Input

5 5 0
3 1 2 9 4
1 5
4 4
1 4
1 3
2 5

Sample Output

3
4
15
11
3

Data Constraint
【GDOI2018模拟9.21】数列

题解

首先这样的二进制题目一般都是用trie来解决的
设sum[i][j]=ai xor xi+1… xor xj
有sum[i][j]=sum[i][k] xor sum[k+1][j]
那么我们可以构一个可持久化trie,把前缀和都挂上去,那么每次询问就可以做到n log 级别
考虑分块
我们可以与处理一个an[x][y]表示max(ed[y]t1=be[x]ed[y]t2=be[y]sum[t1][t2])
那么在算答案的时候我们只需要计算两端中至少有一个不在括住的完整的块里面的最大值了,复杂度nnlogn级别的了

贴代码

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#define fo(i,a,b) for(i=a;i<=b;i++)
#define fo1(i,b,a) for(i=b;i>=a;i--)
const int maxn=2e5+5,bl=155;

using namespace std;

int a[maxn],root[maxn],bb[maxn],ee[maxn],cc[30],sum[maxn];
int g[maxn][bl];
int be[bl],ed[bl],an[bl][bl];
int go[maxn*40][3];
int i,j,k,l,m,n,q,x,y,z,now,qu,tot,t1,t2,p,ans,t,r,ss;
bool bz;

void ge(int x,int y){
    int j;
    tot=0;
    fo1(j,29,0){
        if ((z & cc[j])>0) p=1; else p=0; p=p xor 1;
        if (go[go[x][p]][2]-go[go[y][p]][2]!=0){
            x=go[x][p]; y=go[y][p]; tot=tot+cc[j];
        } else{
            p=p xor 1;
            x=go[x][p]; y=go[y][p];
        }
    }
    if (bz) tot=max(tot,z);
}
int main(){
    freopen("sequence.in","r",stdin);
    freopen("sequence.out","w",stdout);
    scanf("%d%d%d",&n,&q,&t);
    cc[0]=1;
    fo(i,1,30) cc[i]=cc[i-1]*2;
    fo(i,1,n){
        scanf("%d",&a[i]);
        x=x xor a[i];
        sum[i]=x;
        root[i]=++now;
        y=root[i-1];
        z=root[i]; go[z][2]=i;
        fo1(j,29,0){
            if ((x & cc[j])>0){
                go[z][0]=go[y][0]; go[z][1]=++now; z=now; go[now][2]=go[go[y][1]][2]+1;
                y=go[y][1];
            } else{
                go[z][1]=go[y][1]; go[z][0]=++now; z=now; go[now][2]=go[go[y][0]][2]+1;
                y=go[y][0];
            }
        }
    }
    x=trunc(sqrt(n))-1;
    be[1]=1; ed[1]=1+x; y=1; z=1+x; bb[1]=1; ee[1+x]=1;
    while (z<=n){
        if (z+x>=n){
            be[y+1]=ed[y]+1;
            ed[y+1]=n; y++; bb[be[y]]=y; ee[ed[y]]=y; break;
        }
        be[y+1]=ed[y]+1; y++;
        ed[y]=be[y]+x;
        bb[be[y]]=y; ee[ed[y]]=y;
        z=ed[y];
    }
    qu=y;
    fo(i,1,qu){
        ans=0;
        fo1(j,i,1){
            fo(k,be[i],ed[i]){
                bz=false;
                y=root[k]; x=root[be[j]-1]; z=sum[k];
                if (be[j]>=2) x=root[be[j]-2]; else bz=true;
                ge(x,y);
                ans=max(ans,tot);
            }
            an[i][j]=ans;
        }
    }
    ans=0;
    fo(i,1,q){
        scanf("%d%d",&x,&y);
        x=(x+t*ans)%n+1;
        y=(y+t*ans)%n+1;
        l=min(x,y);
        r=max(x,y);
        x=l; y=r;
        while (y && ee[y]==0) y--;
        while (x<=n && bb[x]==0) x++;
        t1=bb[x]; t2=ee[y];
        ans=0;
        if (x>0 && y>0)
        while (t2>=t1){
            ans=max(ans,an[t2][t1]);
            t2--;
        }
        y=max(y,l);
        x=min(x,r);
        fo(j,y,r){
            z=sum[j];
            bz=false;
            ss=max(0,l-2); if (l==1) bz=true;
            ge(root[ss],root[j]);
            ans=max(ans,tot);
        }
        fo(j,l,x){
            bz=false;
            z=sum[j-1];
            ge(root[j-1],root[r]);
            ans=max(ans,tot);
        }
        printf("%d\n",ans);
    }
    return 0;
}
相关标签: trie