AcWing269 Fotile模拟赛L(可持久化Trie)

分块预处理,表示f[][],第i块到第j个数的答案

这样做的时候就可以大块直接查询,小块暴力查询

#include<bits/stdc++.h>
#define getsz(p) (p?p->sz:0)
using namespace std;
typedef long long ll;
typedef pair<ll,int> pll;
const int N=1e5+10;
struct node{
    ll sz;
    node * nxt[2];
}*rt[N],pool[N*30];
ll f[400][16000];
ll s[N],idx,n,block,B;
node *copynode(node *rt){
    node *p=pool+(++idx);
    pool[idx]=*rt;
    return p;
}
node* insert(node* rt, int x, int dep){
    node *p;
    if(rt) p = copynode(rt);
    else{
        p=pool+(++idx);
        p->sz=0;
    }
    ++p->sz;
    if(dep < 0) return p;

    int y = (x>>dep)&1;
    if(!y) p->nxt[0] = insert(p->nxt[0], x, dep-1);
    else p->nxt[1] = insert(p->nxt[1], x, dep-1);

    return p;
}
ll query(node* pL, node* pR, int x, int dep){
    int diff, y;
    ll ans = 0;
    for(int dep=30;dep>=0;dep--){
        y = (x>>dep)&1;
        if(!pL){
            diff = getsz(pR->nxt[!y]);
            if(diff){
                ans += (1<<dep);
                pR = pR->nxt[!y];
            }
            else pR = pR->nxt[y];
        }
        else{
            diff = getsz(pR->nxt[!y]) - getsz(pL->nxt[!y]);
            if(diff){
                ans += (1<<dep);
                pL = pL->nxt[!y];
                pR = pR->nxt[!y];
            }
            else{
                pL = pL->nxt[y];
                pR = pR->nxt[y];
            }
        }
    }
    return ans;
}
ll dp[500][14000];
void init(){
    B = sqrt(n);
    for(int i=0;i<=n;i+=B){
        for(int j=i+1;j<=n;j++){
            if(i==0) dp[i/B][j] = max(dp[i/B][j-1], query(0, rt[j], s[j], 30));
            else dp[i/B][j] = max(dp[i/B][j-1], query(rt[i-1], rt[j], s[j],30));
        }
    }
}
int main(){
    ios::sync_with_stdio(false);
    int m;
    cin>>n>>m;
    int i;
    rt[0]=insert(rt[0],0,30);
    for(i=1;i<=n;i++){
        int x;
        cin>>x;
        s[i]=s[i-1]^x;
        rt[i]=insert(rt[i-1],s[i],30);
    }
    init();
    ll last=0;
    while(m--){
        ll l,r;
        cin>>l>>r;
        l = (l+last)%n + 1;
        r = (r+last)%n + 1;
        if(l>r)
            swap(l,r);
        l--;
        int x=(l/B+1)*B;
        if(x<=r){
            last=dp[l/B+1][r];
        }
        else
            last=0;
        for(i=l;i<x&&i<=r;i++){
            last=max(last,query(rt[i],rt[r],s[i],30));
        }
        cout<<last<<endl;
    }
    return 0;
}
View Code

 

posted @ 2020-08-12 20:03  朝暮不思  阅读(140)  评论(0编辑  收藏  举报