[P4735] 最大异或和 - 可持久化Trie

Description

给定一个非负整数序列 \(\{a\}\),初始长度为 \(n\)

\(m\) 个操作,有以下两种操作类型:

  1. A x:添加操作,表示在序列末尾添加一个数 \(x\),序列的长度 \(n+1\)
  2. Q l r x:询问操作,你需要找到一个位置 \(p\),满足 \(l \le p \le r\),使得: $
    a[p] \oplus a[p+1] \oplus ... \oplus a[N] \oplus x$ 最大,输出最大是多少。

Solution

即求 \(s[p-1] \oplus (sum \oplus x)\) 的最大值,很容易想到可持久化 0-1 Trie

有点卡常

#include <bits/stdc++.h>
using namespace std;

const int N = 15000005;
const int lgn = 23;

int ind;
int ch[N][2],siz[N],head[N];
int n,m,a[N],s[N],t1,t2,t3,sum;
char op[3];

void insert(int x) {
    //cout<<"insert "<<x<<" by "<<n<<endl;
    head[n]=++ind;
    int p=ind,q=head[n-1];
    ch[p][0]=ch[q][0];
    ch[p][1]=ch[q][1];
    siz[p]=siz[q]+1;
    //cout<<p<<","<<q<<endl;
    for(int i=lgn;i>=0;--i) {
        int t=(x>>i)&1;
        ch[p][t]=++ind;
        p=ind;
        q=ch[q][t];
        ch[p][0]=ch[q][0];
        ch[p][1]=ch[q][1];
        siz[p]=siz[q]+1;
        //cout<<p<<","<<q<<endl;
    }
}

int query(int l,int r,int x) {
    //cout<<"query "<<l<<","<<r<<" "<<x<<endl;
    int p=head[r-1],q=l>1?head[l-2]:0;
    int ans=0;
    for(int i=lgn;i>=0;--i) {
        int t=(x>>i)&1;
        if(siz[ch[p][!t]]-siz[ch[q][!t]]) {
            p=ch[p][!t];
            q=ch[q][!t];
            ans|=1<<i;
        }
        else {
            p=ch[p][t];
            q=ch[q][t];
        }
    }
    return ans;
}

signed main() {
    ios::sync_with_stdio(false);
    int _n;
    scanf("%d%d",&_n,&m);
    insert(0);
    for(int i=1;i<=_n;i++) {
        ++n;
        scanf("%d",a+i);
        s[i]=s[i-1]^a[i];
        insert(s[i]);
        //8print();
    }
    sum=s[n];
    for(int i=1;i<=m;i++) {
        scanf("%s",op);
        if(op[0]=='A') {
            scanf("%d",&t1);
            a[++n]=t1;
            s[n]=s[n-1]^a[n];
            insert(s[n]);
            sum=s[n];
        }
        else {
            scanf("%d%d%d",&t1,&t2,&t3);
            printf("%d\n",query(t1,t2,t3^sum));
        }
    }
}

猜你喜欢

转载自www.cnblogs.com/mollnn/p/13196335.html