最大异或和

最大异或和

https://ac.nowcoder.com/acm/problem/51120

分析

首先,我们将题目化简一下
由于
Pre[]表示异或前缀和

所以我们其实只需要维护Pre[]即可
每次在一定的区间内查询与当前Pre[N]异或的最大值即可
由于是区间查询,并且需要动态维护
所以我们可以使用类似于主席树的维护方式进行维护
可持久化01Trie
动态进行开点
由于每次只会修改到个节点
查询的时候同样为个节点
所以总的
时间复杂度:
空间复杂度:
期望得分:100分

代码

//P4735
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>

#define LL long long
#define Cl(X,Y) memset((X),(Y),sizeof(X))
#define FOR(i,A,B) for(int i=A;i<=B;i++)
#define BOR(i,A,B) for(int i=A;i>=B;i--)
#define Lowbit(X) (X & (-X))
#define INF 0x3f3f3f3f
#define Rson (X<<1|1)
#define Lson (X<<1)
using namespace std;
const int MaxN=6e5+10,MaxM=100;

int Child[MaxN<<6][2],Size,Cnt[MaxN<<6][2];
int Ans,Root[MaxN],u,v,w;
int Total,Test,Bit[MaxM],Loc;
int Num[MaxN],Pre[MaxN],Two[MaxM]={1};
char Opt[5];

inline void File() {
    freopen(".in","r",stdin);
    freopen(".out","w",stdout);
}

inline void Copy(int Res,int New) { Child[Res][1]=Child[New][1]; Child[Res][0]=Child[New][0]; Cnt[Res][0]=Cnt[New][0]; Cnt[Res][1]=Cnt[New][1]; }
inline int Update(int New,int Temp,int Mine) {
    if(Temp==-1) return 0;
    Bit[Temp]=((Mine>>Temp) & 1);
    int Res=++Size;
    Copy(Res,New);
    Cnt[Res][Bit[Temp]]++;
    if(Bit[Temp]) { Child[Res][1]=Update(Child[New][1],Temp-1,Mine); }
    else { Child[Res][0]=Update(Child[New][0],Temp-1,Mine); }
    return Res;
}

inline int Get(int Left,int Right,int Temp,int Mine) {
    if(Temp==-1) return 0;
    Bit[Temp]=((Mine>>Temp) & 1);
    if(Bit[Temp]) {
        if(Cnt[Right][0]-Cnt[Left][0]>0) { return (Two[Temp]|Get(Child[Left][0],Child[Right][0],Temp-1,Mine)); }
        else { return Get(Child[Left][1],Child[Right][1],Temp-1,Mine); }
    } else {
        if(Cnt[Right][1]-Cnt[Left][1]>0) { return (Two[Temp]|Get(Child[Left][1],Child[Right][1],Temp-1,Mine)); }
        else { return Get(Child[Left][0],Child[Right][0],Temp-1,Mine); }
    }
}

signed main() {
    // File();
    // ios::sync_with_stdio(false);
    FOR(i,1,30) Two[i]=Two[i-1]*2; 
    cin>>Total>>Test;
    Root[0]=Update(0,23,0);
    FOR(i,1,Total) { cin>>Num[i]; Pre[i]=Pre[i-1]^Num[i]; Root[i]=Update(Root[i-1],23,Pre[i]); }
    while(Test--) {
        scanf("%s",Opt+1);
        if(Opt[1]=='A') { cin>>u; Num[++Total]=u; Pre[Total]=Pre[Total-1]^Num[Total]; Root[Total]=Update(Root[Total-1],23,Pre[Total]); } 
        else { 
            scanf("%d %d %d",&u,&v,&w);
            if(v==1) printf("%d\n",Pre[Total]^w);
            else if(u!=1) printf("%d\n",Get(Root[u-2],Root[v-1],23,w^Pre[Total])); 
            else printf("%d\n",Get(0,Root[v-1],23,w^Pre[Total]));
        }
    }
        // fclose(stdin);
        // fclose(stdout);
       // system("pause");
        return 0;
    }
全部评论

相关推荐

10-07 20:48
门头沟学院 Java
听说改名就会有offer:可能是实习上着班想到后面还要回学校给导师做牛马,看着身边都是21-25的年纪,突然emo了了
点赞 评论 收藏
分享
4 1 评论
分享
牛客网
牛客企业服务