P4735 最大异或和 01可持久化Trie树模板

原题:https://www.luogu.org/problemnew/show/P4735

题解:观察一下式子,将a数组求一个异或前缀和,其实就是s[n]^x^s[p-1]的最大值 p∈[l,r],就是区间对一个数的异或的最最大值。假设我们把这个区间放进Trie字典树中,对于一个x的询问,可以用贪心的思想,反着走找到最大值。但是确定出给定区间的Trie树,用类似于主席树的思想,建一颗动态开点的Trie树,询问时用前缀和减掉就行了。洛谷的评测很神奇,不开o2过不了。

#include
#define reg register
using namespace std;
const int N=600010;
int ch[N*30][2],cnt[N*30],T[N];
int n,m,s[N],tot;
char str[10];
inline int rd(){
    int x=0;int f=1;char s=getchar();
    while(!isdigit(s)) f=(s=='-'?-1:f),s=getchar();
    while(isdigit(s)) x=(x<<1)+(x<<3)+s-'0',s=getchar();
    return x*f;
}
void ins(int a,int b,int t,int x){
    if(t<0) return ;
    int i=(x>>t)&1; 
    ch[a][!i]=ch[b][!i];
    ch[a][i]=++tot;
    cnt[ch[a][i]]=cnt[ch[b][i]]+1;
    ins(ch[a][i],ch[b][i],t-1,x);
}
int query(int a,int b,int t,int x){
    if(t<0) return 0;
    int i=(x>>t)&1;
    if(cnt[ch[b][!i]]>cnt[ch[a][!i]]) return (1<=0;i--) putchar('0'+d[i]);puts("");
	
}
int main(){
//	freopen("p4735.in","r",stdin);
    n=rd();m=rd();
    T[0]=++tot;ins(T[0],0,25,0);
    for(int i=1;i<=n;i++){
        s[i]=rd();s[i]^=s[i-1]; 
        T[i]=++tot;ins(T[i],T[i-1],25,s[i]);
    } 
    for(int i=1;i<=m;i++){
        scanf("%s",&str);int x,l,r;
        if(str[0]=='A'){
            s[++n]=rd();s[n]^=s[n-1];
            T[n]=++tot;ins(T[n],T[n-1],25,s[n]);
        }else{
            l=rd()-1;r=rd()-1;x=rd();
            int ans=0;
            if(l==0) ans=query(0,T[r],25,x^s[n]);//
            else ans=query(T[max(0,l-1)],T[r],25,x^s[n]);
        	print(ans);
		}
    }
    return 0;
}

 

你可能感兴趣的:(Trie/可持久化Trie)