题目链接
给定一个非负整数序列 a ,初始长度为 N 。
有 M 个操作,有以下两种操作类型:
A x
:添加操作,表示在序列末尾添加一个数 x ,序列的长度 N 增大 1 。
Q l r x
:询问操作,你需要找到一个位置 p ,满足 l≤p≤r ,使得: a[p] xor a [p+1] xor … xor a[N] xor x 最 大,输出这个最大值。
输入格式
第一行包含两个整数 N,M ,含义如问题描述所示。
第二行包含 N 个非负整数,表示初始的序列 A。
接下来 M 行,每行描述一个操作,格式如题面所述。
输出格式
每个询问操作输出一个整数,表示询问的答案。
每个答案占一行。
数据范围
N,M≤3×105,0≤a[i]≤107 。
输入样例:
输出样例:
解题思路
可持久化 trie
可持久化 trie 关键在于维护所有版本的信息,每次插入一个数,每次创建一个根节点,并且将前面的信息复制过来,但不是完全复制,而是利用了本身的信息,如下:

即插入一个数时,要利用上一个版本的信息,一层一层的进行操作,如果上一个版本有信息,则将该层信息复制过来,再生成本层应该生成的信息,这样所有的信息都能维护到
本题即求 sp−1⨁sn 的最大值,其中 si 为前缀异或值,l≤p≤r,如果在 1∼r 范围内,则可利用可持久化 trie 解决(root[r] 维护了前 r 个版本的信息),可以在每个节点上维护以该节点为子树的最大下标,当需要该节点时只需要判断该下标是否不小于 l 即可
- 时间复杂度:O((m+n)×logn)
代码
#include <bits/stdc++.h>
#define help {cin.tie(NULL); cout.tie(NULL);}
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }
template <typename T> void inline read(T &x) {
int f = 1; x = 0; char s = getchar();
while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
x *= f;
}
const int N=6e5+5,M=N*24;
int n,m,s[N],tr[M][2],root[N],max_id[M],idx;
void insert(int i,int k,int p,int q)
{
if(k<0)
{
max_id[q]=i;
return ;
}
int v=s[i]>>k&1;
if(p)tr[q][v^1]=tr[p][v^1];
tr[q][v]=++idx;
insert(i,k-1,tr[p][v],tr[q][v]);
max_id[q]=max(max_id[tr[q][0]],max_id[tr[q][1]]);
}
int ask(int l,int root,int C)
{
int p=root;
for(int i=23;i>=0;i--)
{
int t=C>>i&1;
if(max_id[tr[p][t^1]]>=l)p=tr[p][t^1];
else
p=tr[p][t];
}
return C^s[max_id[p]];
}
int main()
{
scanf("%d%d",&n,&m);
root[0]=++idx,max_id[0]=-1;
insert(0,23,0,root[0]);
for(int i=1;i<=n;i++)
{
int x;
scanf("%d",&x);
s[i]=s[i-1]^x;
root[i]=++idx;
insert(i,23,root[i-1],root[i]);
}
char op[2];
int l,r,x;
while(m--)
{
scanf("%s",op);
if(*op=='A')
{
scanf("%d",&x);
n++;
s[n]=s[n-1]^x;
root[n]=++idx;
insert(n,23,root[n-1],root[n]);
}
else
{
scanf("%d%d%d",&l,&r,&x);
printf("%d\n",ask(l-1,root[r-1],s[n]^x));
}
}
return 0;
}
__EOF__
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!