CF-282-E-Trie

282-E 题目大意

给定一个长为\(n\)的序列\(a\),要求选一个前缀与一个不相交的后缀,求这些元素异或结果的最大值。


Solution

最大的异或值,首先就要想到\(Trie\)

把所有前缀加入\(Trie\),然后枚举后缀,一边在\(Trie\)中查询最大异或值,一边删掉一个前缀,避免会产生相交的前后缀。

注意要spj掉前缀为空与后缀为空的特殊情况,时间复杂度\(O(nlogn)\)

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

const int N=1e5+10;
int ch[N*61][2],cnt[N*31];
int idx=0;

void update(ll x,int k){
    int p=0;
    for(int i=60;~i;i--){
        int j=(x>>i)&1;
        if(!ch[p][j]) ch[p][j]=++idx;
        p=ch[p][j];
        cnt[p]+=k;
    }
}

ll query(ll x){
    int p=0;
    ll res=0;
    for(int i=60;~i;i--){
        int j=(x>>i)&1;
        if(cnt[ch[p][!j]]){
            res|=(1LL<<i);
            p=ch[p][!j];
        }else{
            p=ch[p][j];
        }
    }
    return res;
}

void solve(){
    int n;
    cin>>n;
    ll pre=0,suf=0;
    vector<ll> a(n+1);
    update(0,1);
    for(int i=1;i<=n;i++){
        cin>>a[i];
        pre^=a[i];
        update(pre,1);
    }
    ll ans=query(0);
    for(int i=n;~i;i--){
        suf^=a[i];
        update(pre,-1);
        pre^=a[i];
        ans=max(ans,query(suf));
    }
    cout<<ans<<'\n';
}

int main(){
    ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    int T=1;
    //cin>>T;
    while(T--){
        solve();
    }
    return 0;
}
posted @ 2024-01-17 02:29  fengxue-K  阅读(17)  评论(0)    收藏  举报