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

jzoj5382 [GDOI2018模拟9.21]数列 可持久化trie+分块

程序员文章站 2024-02-12 22:42:10
...

Description


jzoj5382 [GDOI2018模拟9.21]数列 可持久化trie+分块
n,q<=20000
a[i]<=10^9

Solution


今天场外体验noi刺激战场,发现我只会做T1这种送分题(⊙ˍ⊙),还没切。果然人菜还是要多读书

首先做前缀和,变成两个点的问题
与异或相关可以考虑trie。一个暴力的做法就是建可持久化trie然后枚举查询最大异或和
看到n很小一个想法就是对区间分块,预处理f[i,j]表示块i的起点到j这一段的答案,然后搞搞就可以了

如果没有强制在线可以莫队,然鹅直接莫队就有90分

Solution


#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <math.h>
#define rep(i,st,ed) for (int i=st;i<=ed;++i)
#define drp(i,st,ed) for (int i=st;i>=ed;--i)

typedef long long LL;
const int N=20005;
const int B=185;

int rec[N*60][2],root[N],sum[N*60],tot;
int st[B],ed[B],bel[N],a[N];
int wjp[B][N],ans;

int read() {
    int x=0,v=1; char ch=getchar();
    for (;ch<'0'||ch>'9';v=(ch=='-')?(-1):(v),ch=getchar());
    for (;ch<='9'&&ch>='0';x=x*10+ch-'0',ch=getchar());
    return x*v;
}

int ins(int x,int v) {
    int y=++tot; int ret=y;
    drp(i,29,0) {
        rec[y][0]=rec[x][0];
        rec[y][1]=rec[x][1];
        sum[y]=sum[x]+1;
        int now=(v&(1<<i))!=0;
        x=rec[x][now];
        y=rec[y][now]=++tot;
    }
    sum[y]=sum[x]+1;
    return ret;
}

int query(int pre,int x,int v) {
    int ret=0;
    drp(i,29,0) {
        int now=(v&(1<<i))!=0;
        if (sum[rec[x][!now]]-sum[rec[pre][!now]]>0) {
            x=rec[x][!now];
            pre=rec[pre][!now];
            ret+=1<<i;
        } else {
            x=rec[x][now];
            pre=rec[pre][now];
        }
        // if (ret+(1<<i+1)-1<=ans) return ret;
    }
    return ret;
}

int main(void) {
    freopen("data.in","r",stdin);
    freopen("myp.out","w",stdout);
    int n=read(),q=read(),t=read();
    int m=sqrt(n);
    root[0]=ins(0,0);
    rep(i,1,n) {
        a[i]=a[i-1]^read();
        root[i]=ins(root[i-1],a[i]);
        bel[i]=(i-1)/m+1;
        if (!st[bel[i]]) st[bel[i]]=i;
        ed[bel[i]]=std:: max(ed[bel[i]],i);
    }
    rep(i,1,m) {
        rep(j,st[i],n) {
            wjp[i][j]=std:: max(wjp[i][j-1],query((st[i]-1)?root[st[i]-2]:0,root[j],a[j]));
        }
    }
    for (int lastans=0,cnt=0;q--;cnt++) {
        int l=read(),r=read(); ans=0;
        int x=(l+t*(LL)lastans)%n+1;
        int y=(r+t*(LL)lastans)%n+1;
        if (x>y) std:: swap(x,y);
        int px=bel[x],py=bel[y];
        if (py==px) {
            rep(j,x,y) ans=std:: max(ans,query((x-1)?(root[x-2]):0,root[y],a[j]));
        } else {
            ans=wjp[px+1][y];
            rep(j,x-1,ed[px]) ans=std:: max(ans,query((x-1)?(root[x-2]):0,root[y],a[j]));
            rep(j,st[py],y) ans=std:: max(ans,query((x-1)?(root[x-2]):0,root[y],a[j]));
        }
        printf("%d\n", ans); lastans=ans;
    }
    return 0;
}
相关标签: jzoj