[可持久Trie] 可持久Trie板子

最大异或和

可持久trie板题

实现两个操作:

  1. 在序列 a a a末尾添加一个数 x x x,并且序列长度增大 1 1 1
  2. 询问求一个位置 p ∈ [ l , r ] p\in [l,r] p[l,r],最大化 ( ⨁ p n a i ) ⊕ x (\bigoplus_p^na_i)\oplus x (pnai)x,其中 x x x为读入数

考虑前缀和,记 ⨁ 1 i a i = s i \bigoplus_1^ia_i=s_i 1iai=si,记 v a l = s n ⊕ x val=s_n\oplus x val=snx
现目标最大化 a p ⊕ v a l , p ∈ [ l − 1 , r − 1 ] a_p\oplus val,p\in[l-1,r-1] apval,p[l1,r1]

进阶指南写得真的好啊:一步一步加限制,想解法
不考虑限制,朴素trie即可结局
再考虑 p ≤ r − 1 p\le r-1 pr1的限制,运用可持久trie,在root[r-1]里访问即可
最后考虑 p ∈ [ l − 1 , r − 1 ] p\in[l-1,r-1] p[l1,r1],即访问时不能访问到 < l − 1 <l-1 <l1的点,维护一个tag即可,记录节点是第几个二进制数能访问到的,且最大化tag
tag的算法一定义一下

注意空间
听说20倍到32倍左右

#include<bits/stdc++.h>
using namespace std;
#define in Read()
typedef long long ll;
ll in{
	ll i=0,f=1;char ch=0;
	while(!isdigit(ch)&&ch!='-') ch=getchar();
	if(ch=='-') ch=getchar(),f=-1;
	while(isdigit(ch)) i=(i<<3)+(i<<1)+ch-48,ch=getchar();
	return i*f;
}

const int N=1e6+5;
int n,m,sz,trie[N*24][2],tag[N*24],root[N],s[N];
char opt[3];

void insert(int t,int k,int pre,int now){
	if(k<0){
		tag[now]=t;
		return;
	}
	int c=(s[t]>>k)&1;
	if(pre) trie[now][c^1]=trie[pre][c^1];
	trie[now][c]=++sz;
	insert(t,k-1,trie[pre][c],trie[now][c]);
	tag[now]=max(tag[trie[now][0]],tag[trie[now][1]]);
	return;
}

int query(int val,int k,int now,int low){
	if(k<0) return val^s[tag[now]];
	int c=(val>>k)&1;
	if(tag[trie[now][c^1]]>=low)
		return query(val,k-1,trie[now][c^1],low);
	else
		return query(val,k-1,trie[now][c],low);
}

int main(){
	n=in,m=in;
	tag[0]=-1;
	root[0]=++sz;
	insert(0,23,0,root[0]);
	for(int i=1;i<=n;++i){
		int x=in;
		s[i]=s[i-1]^x;
		root[i]=++sz;
		insert(i,23,root[i-1],root[i]);
	}
	for(int i=1;i<=m;++i){
		scanf("%s",opt);
		if(opt[0]=='A'){
			int x=in;
			root[++n]=++sz;
			s[n]=s[n-1]^x;
			insert(n,23,root[n-1],root[n]);
		}else{
			int l=in,r=in,x=in;
			int val=s[n]^x;
			printf("%d\n",query(val,23,root[r-1],l-1));
		}
	}
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值