P4735 Maximum XOR and Persistent Trie Template Question

Click here for the topic

He requires the maximum value of the XOR sum from the position in an interval to the end. Let's convert it. Let S[i] denote the result of the XOR of the first i positions, that is, the prefix sum of the XOR value.
So the requirement of the title a[p] ^ a[p+1] ^... a[n] ^ x = s[p-1] ^ s[n] ^ x. So the question is equivalent to becoming, given a value val = s[n]^x, find a position p that satisfies l-1 =< p <= r-1, making the value of s[p] ^ val the largest
In this case, we only need to make the trie persistent, and each time the interval is asked for the legal position (that is, whether there is a legal position between the two versions) is to check whether the interval condition of the opposite position on each val is legal, using a cnt array Record the information of the version corresponding to the end node of the trie, so as to achieve the interval requirement of p.
Finally, if the left end of the interval in question is 1, it may be the largest XOR sum from 0. Therefore, we need to insert During operation, pre-process the insertion of a node 0 to solve this problem.

See the code for specific operations:
you can refer to page P252 of the Algorithm Competition Advanced Guide

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const int MAXN = 6e5+7;
//可持久化Trie
int n,m;
int trie[MAXN*24][2],root[MAXN<<1],cnt[MAXN*24],size;
int s[MAXN<<1];//异或和

void insert(int now,int pre,int k,int x)
{
    
    
	if(k < 0) return ;
	int i = (x>>k)&1;//把第k位拿上来
	trie[now][!i] = trie[pre][!i];//之前的都连在一起
	trie[now][i] = ++size;//新插入的单独开节点
	cnt[trie[now][i]] = cnt[trie[pre][i]]+1;//记录当前的版本
	insert(trie[now][i],trie[pre][i],k-1,x);//递归插入
}

int query(int r,int l,int k,int x)
{
    
    
	if(k < 0) return 0;
	int i = (x>>k)&1;
	if(cnt[trie[r][!i]] > cnt[trie[l][!i]])//代表这个区间可行
		return (1<<k) + query(trie[r][!i],trie[l][!i],k-1,x);
	else
		return query(trie[r][i],trie[l][i],k-1,x);
}

int main()
{
    
    
	scanf("%d%d",&n,&m);
	//要把0先插入trie中
	root[0] = ++size;
	insert(root[0],0,24,0);
	for(int i = 1;i <= n;i ++){
    
    
		int x;
		scanf("%d",&x);
		s[i] = s[i-1]^x;
		root[i] = ++size;
		insert(root[i],root[i-1],24,s[i]);
	}
	while(m--){
    
    
		char op;int l,r,x;
		cin>>op;
		switch(op){
    
    
			case 'A':
				scanf("%d",&x);
				n++;//在序列尾添加元素的话 就是在尾部申请一个新的节点
				s[n] = s[n-1]^x;
				root[n] = ++size;
				insert(root[n],root[n-1],24,s[n]);
				break;
			case 'Q':
				scanf("%d%d%d",&l,&r,&x);
				l--,r--;
				//printf("-----\n");
				int ans;
				if(l == 0) ans = query(root[r],0,24,s[n]^x);
				else ans = query(root[r],root[l-1],24,s[n]^x);
				//printf("-----\n");
				printf("%d\n",ans);
				break;
		}
	}
	return 0;
}

Guess you like

Origin blog.csdn.net/weixin_45672411/article/details/108487032