【字典树】 P4735 最大异或和

139 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第23天,点击查看活动详情

最大异或和

题目描述

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

mm 个操作,有以下两种操作类型:

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

输入格式

第一行包含两个整数 N,MN,M,含义如问题描述所示。
第二行包含 NN个非负整数,表示初始的序列A A
接下来 MM行,每行描述一个操作,格式如题面所述。

输出格式

假设询问操作有 TT 个,则输出应该有 TT 行,每行一个整数表示询问的答案。

样例 #1

样例输入 #1

5  5
2  6 4 3 6
A 1 
Q 3 5 4 
A 4
Q 5 7 0 
Q 3 6 6

样例输出 #1

4
5
6

提示

对于测试点 121-2N,M5N,M \le 5
对于测试点 373-7N,M80000N,M \le 80000
对于测试点 8108-10N,M300000N,M \le 300000
其中测试点 1,3,5,7,91, 3, 5, 7, 9保证没有修改操作。
0a[i]1070 \le a[i] \le 10^7

0-1字典树

#include<cstdio>
#include<iostream>
using namespace std;
const int maxn=3e7+10;
int n,m,k;
int a[maxn],sum[maxn];
struct tire{
	int size,son[2];
}tree[maxn];
int root[maxn];
int build(int x)
{
	int now=++k;
	tree[now].size=1;
	if(x==0)return now;
	tree[now].son[0]=build(x-1);
	return now;	
}
int update(int pre,int x,int pos)
{
	int now=++k;
	if(pos==0){
		tree[now].size=tree[pre].size+1;
		return now;
	}
	tree[now]=tree[pre];
	tree[now].son[1&(x>>(pos-1))]=update(tree[pre].son[1&(x>>(pos-1))],x,pos-1);
	tree[now].size=tree[tree[now].son[0]].size+tree[tree[now].son[1]].size;
	return now;
}
int query(int pre,int now,int x,int pos)
{
	if(!pos)return 0;
	return (tree[tree[now].son[1^(1&(x>>(pos-1)))]].size-tree[tree[pre].son[1^(1&(x>>(pos-1)))]].size)?
			query(tree[pre].son[1^(1&(x>>(pos-1)))],tree[now].son[1^(1&(x>>(pos-1)))],x,pos-1)+(1<<(pos-1)):
			query(tree[pre].son[1&(x>>(pos-1))],tree[now].son[1&(x>>(pos-1))],x,pos-1);
}
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
		scanf("%d",&a[i]),
		sum[i]=sum[i-1]^a[i];
	root[0]=++k;
	for(int i=0;i<=n;i++)
		root[i+1]=update(root[i],sum[i],25);
	for(int i=1,l,r,x;i<=m;i++){
		char opt;
		scanf("\n%c",&opt);
		if(opt=='A')scanf("%d",&x),sum[n+1]=sum[n]^x,root[n+2]=update(root[n+1],sum[n+1],25),n++;
		else{
			scanf("%d%d%d",&l,&r,&x);
			printf("%d\n",query(root[l-1],root[r],x^sum[n],25));
		}
	}
	return 0;
}