P4735 Pregunta de plantilla de ensayo persistente y XOR máximo

Haga clic aquí para ver el tema

Requiere el valor máximo de la suma XOR desde la posición en un intervalo hasta el final. Vamos a convertirlo. Sea S [i] el resultado del XOR de las primeras i posiciones, es decir, la suma del prefijo del valor XOR.
Entonces, el requisito del título a [p] ^ a [p + 1] ^ ... a [n] ^ x = s [p-1] ^ s [n] ^ x. Entonces la pregunta es equivalente a convertirse, dado un valor val = s [n] ^ x, encontrar una posición p que satisfaga l-1 = <p <= r-1, haciendo que el valor de s [p] ^ val sea el más grande
En este caso, solo necesitamos hacer que el trie sea persistente, y cada vez que se solicita el intervalo para la posición legal (es decir, si existe una posición legal entre las dos versiones) es para verificar si la condición de intervalo de la posición opuesta en cada val es legal, usando una matriz cnt Registrar la información de la versión correspondiente al nodo final del trie, para lograr el requisito de intervalo de p.
Finalmente, si el extremo izquierdo del intervalo en cuestión es 1, puede ser la mayor suma XOR de 0. Por lo tanto, necesitamos insertar Durante la operación, procese previamente la inserción de un nodo 0 para resolver este problema.

Consulte el código para operaciones específicas:
puede consultar la página P252 de la Guía avanzada de competencia de algoritmos

#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;
}

Supongo que te gusta

Origin blog.csdn.net/weixin_45672411/article/details/108487032
Recomendado
Clasificación