可持久化0-1 Trie 简介
Trie树是字符串问题中应用极为广泛的一种数据结构,可以拓展出AC自动机、后缀字典树等实用数据结构。
然而在此我们考虑0-1 Trie的应用,即在序列最大异或问题中的应用。
这里的异或是指按位异或。按位异或有很多重要的性质。比如可拆分性,每个位可以进行单独处理后线性合并得到最终结果。
同时按位异或也是可减的。比如0111 ^ 1010 = 1101, 那么 1101 ^ 1010 = 0111. 证明从略。
首先我们考虑0-1 Trie的版本,也就是
给定一个序列a[i], 每次询问一个数x与a[i]中各元素能得到的按位异或的最大值。
暴力自然是O(n^2)的。但是我们想到之前的可拆分性,是否能将每个位单独考虑?但是,第一位的选择又会限定第二位的选择范围。即选择第一位是0或1后,第二位的选择就不能从a[i]中的所有元素中进行选择,而要将a[i]分为两份。我们很容易发现这是一个类似树形的问题,所以我们考虑使用树形数据结构。而鉴于多个串根据前缀进行选择性划分的特点,我们使用Trie树来从高位到低位地维护这些0-1串,即0-1 Trie。
注意到这种从高位到低位的选择一定是全局最优的。也就是说,对于异或结果,从高到低考虑,每一位能设成1就设成1. 证明可以利用反证法。
这样我们就利用一个贪心完成了这样的事情。这样的处理是O(n+m)的(常数有32倍)
什么时候需要使用可持久化0-1 Trie呢?我们想,在使用可持久化线段树维护区间K大值得时候,可持久化是否起到了限定区间的作用?同理,在这里,我们也是用可持久化来实现区间的限定。
重要性质:Trie树的节点存在性满足可减性。
我们可以把节点的存在性记录改为节点的数目记录,这样用root[r]中某节点的数目减去root[l-1]中某节点的数目,就可以得到区间中是否存在某个节点。
#include<bits/stdc++.h>
using namespace std; int ch[][],val[],cnt[],root[],ts[],ind,n,m; void insert(int p,int p0,int dep) {
ch[p][]=ch[p0][];
ch[p][]=ch[p0][];
if(dep==) return;
if(ch[p0][ts[dep+]]==) {
ch[p][ts[dep+]]=++ind;
val[ind]=ts[dep+];
cnt[ind]=;
insert(ind,ch[p0][ts[dep+]],dep+);
}
else {
ch[p][ts[dep+]]=++ind;
val[ind]=ts[dep+];
cnt[ch[p][ts[dep+]]]=cnt[ch[p0][ts[dep+]]]+;
insert(ch[p][ts[dep+]],ch[p0][ts[dep+]],dep+);
}
} void trie_insert(int rtx,int num) {
for(int i=;i<=;i++)
ts[i]=(num>>(-i))&;
insert(root[rtx],root[rtx-],);
} int xormax(int rtx,int rty,int num) {
int p=root[rtx], q=root[rty], ans=;
for(int i=;i>=;i--) {
if((num>>i)&) {
if(cnt[ch[q][]]-cnt[ch[p][]]) ans=ans*+, p=ch[p][], q=ch[q][];
else ans=ans*, p=ch[p][], q=ch[q][];
}
else {
if(cnt[ch[q][]]-cnt[ch[p][]]) ans=ans*+, p=ch[p][], q=ch[q][];
else ans=ans*, p=ch[p][], q=ch[q][];
}
}
return ans;
} int main() {
cin>>n;
for(int i=;i<=n;i++) {
int t;
cin>>t;
root[i]=++ind;
trie_insert(i,t);
}
cin>>m;
for(int i=;i<=m;i++) {
int t1,t2,t3;
cin>>t1>>t2>>t3;
t1--;
cout<<xormax(t1,t2,t3)<<endl;
}
}
可持久化0-1 Trie 简介的更多相关文章
- Trie 简介
一.Trie简介 在计算机科学中,Trie,又称字典树.前缀树.单词查找树或键树,是一种树形结构,是一种哈希树的变种.典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎 ...
- 【可持久化0/1Trie】【P4735】最大异或和
Description 给定一个长度为 \(n\) 的序列 \(A\),有 \(m\) 次操作,每次要么在序列尾部再添加一个数,将序列长度 \(n\) 加一,要么给进行一次查询,给定查询参数 \(l, ...
- Apache Flume 1.7.0 各个模块简介
Flume简介 Apache Flume是一个分布式.可靠.高可用的日志收集系统,支持各种各样的数据来源,如http,log文件,jms,监听端口数据等等,能将这些数据源的海量日志数据进行高效收集.聚 ...
- 0.ECMAScript 6 简介
ECMAScript 6简介 ECMAScript 6 简介 ECMAScript 6.0(以下简称 ES6)是 JavaScript 语言的下一代标准,已经在 2015 年 6 月正式发布了.它的目 ...
- HDU4825:Xor Sum 解题报告(0/1 Trie树)
Problem Description Zeus 和 Prometheus 做了一个游戏,Prometheus 给 Zeus 一个集合,集合中包含了N个正整数. 随后 Prometheus 将向 Ze ...
- Libevent:0异步IO简介
一:异步IO简介 大多数的初级编程者都是从阻塞IO调用开始网络编程的.阻塞(同步)IO调用指的是:调用会一直阻塞,不会返回,直到发生下面两种情况之一.要么操作完成,要么经历相当长的时间,网络协议栈自己 ...
- Linux Kernel 0.12 启动简介,调试记录(Ubuntu1804, Bochs, gdb)
PS:要转载请注明出处,本人版权所有. PS: 这个只是基于<我自己>的理解, 如果和你的原则及想法相冲突,请谅解,勿喷. 前置说明 本文作为本人csdn blog的主站的备份.(Bl ...
- zabbix 3.0快速安装简介(centos 6)
zabbix快速安装 系统版本:centos 6 1.yum源配置和zabbix.msyql安装 rpm -ivh http://mirrors.aliyun.com/zabbix/zabbix/3. ...
- zabbix 3.0快速安装简介(centos 7)
zabbix快速安装 系统版本:centos 7 通过yum方法安装Zabbix3.0,安装源为阿里云 yum源配置 rpm -ivh http://mirrors.aliyun.com/zabbix ...
随机推荐
- ES6之常用开发知识点:入门(一)
ES6介绍 ES6, 全称 ECMAScript 6.0 ,2015.06 发版. let 和 const命令 let命令 let 命令,用来声明变量.它的用法类似于var,区别在于var声明的变量全 ...
- Vim 全选命令
ggVG稍微解释一下上面的命令gg 让光标移到首行,在vim才有效,vi中无效V 是进入Visual(可视)模式G 光标移到最后一行选中内容以后就可以其他的操作了,比如:d 删除选中内容y ...
- 剑指offer-面试题49-丑数-空间换时间
/* 题目: 求从1开始的第n个丑数. */ /* 思路: 按顺序列出各个丑数. */ #include<iostream> #include<cstring> #includ ...
- vsftp配置遇到的一些问题
设置匿名登陆的时候,要保证 /var/ftp/ 的所有者 是root,不然会一直提示输入用户名和密码,无法登陆! 上传的权限 local_umask =002 以及 匿名用户 anon_umask=0 ...
- JN_0012:win10的开机启动文件夹
1,登录所有用户时都能开机启动的启动文件夹.所有用户通用的开机启动文件夹地址是 C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp ...
- 百度api识别验证码登录
import time from selenium import webdriver from aip import AipOcr def initial(): """ ...
- Android列表类视图之基本适配器BaseAdapter
说到列表视图,不难联想到前面提到过的数组适配器,但是数组适配器只能搭建文本选择项,扩展能力并不强,Android提供了一种适应性更强的基本适配器BaseAdapter,该适配器允许开发者在别的代码中进 ...
- 如何通过 SSH/Telnet 用 root 权限登录群晖
出于系统安全原因,对 Synology NAS 的 root 访问有限.如果您获取 root 权限,请在命令行界面中用任何属于Local Administrators群组的帐户证书登录 DSM(如Pu ...
- js微信禁用右上角的分享按钮,和vue中微信页面禁用右上角的分享按钮的问题
1.隐藏微信网页右上角的按钮 document.addEventListener('WeixinJSBridgeReady', function onBridgeReady() { // 通过下面这个 ...
- Android_下方弹出菜单的实现
这一功能要用到动画相关知识 实现点击按钮弹出下方输入框,这里点击可弹出一个输入界面,其中包括一个小型计算器. 点击date可弹出datedialog设置date. 1.编写弹出框的布局文件 <? ...