可持久化字典树【模板】

可持久化字典树

P4735 最大异或和

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

const int maxn=6e5+10;
int n,m,sum[maxn],x,l,r,cnt=0;
int ch[maxn*25][2],ver[maxn*25],root[maxn];
//ch表示字典树数组,ver表示每个接节点的版本(第几个字典树),root表示每个点所在的那个字典树的根
char s;

void add(int nw,int pre,int x){//压入当前的根nw,上一个字典树的根pre,这个字典树的编号
  ver[nw]=x;
  for(int i=23;i>=0;i--){
  	int c=(sum[x]>>i)&1;
    ch[nw][!c]=ch[pre][!c];
    ch[nw][c]=++cnt;
    nw=ch[nw][c];pre=ch[pre][c];
    ver[nw]=x;
  }
}

int query(int nw,int limit,int val){//当前字典树的根nw,下限limit,所异或的值val
  int res=0;
  for(int i=23;i>=0;i--){
    int c=(val>>i)&1;
    if(ver[ch[nw][!c]]>=limit) nw=ch[nw][!c],res+=(1<<i);
    else nw=ch[nw][c];
  }
  return res;
}

int main(){
  /*2023.5.1 hewanying P4735 最大异或和 可持久化字典树*/ 
  scanf("%d%d",&n,&m);
  ver[0]=-1;
  root[0]=++cnt;
  add(root[0],0,0);
  for(int i=1;i<=n;i++){
  	scanf("%d",&x);
  	root[i]=++cnt;
  	sum[i]=sum[i-1]^x;
  	add(root[i],root[i-1],i);
  }
  for(int i=1;i<=m;i++){
    scanf(" %c",&s);
    if(s=='A'){
      scanf("%d",&x);
      root[++n]=++cnt;
	  sum[n]=sum[n-1]^x;
      add(root[n],root[n-1],n);
	}
	else{
	  scanf("%d%d%d",&l,&r,&x);
	  printf("%d\n",query(root[r-1],l-1,x^sum[n]));
	}
  }
  return 0;
}
posted @ 2023-05-01 10:32  H_W_Y  阅读(22)  评论(0编辑  收藏  举报