文章历史

2022-08-03: 文章初稿,由于对算法介绍过于少而被管理员打回重造。

2020-08-06:将算法介绍进行扩写,并删除了一些可有可无的内容或玩梗内容。

管理员审核题解辛苦了。

简要题意

(这道题描述是真的长)

你需要维护一个数据结构,支持单点异或和区间求最大异或和。

思路

思维过程

对于这种区间问题,最容易想到的就是线段树。

而对于复杂的异或问题,最容易想到的就是线性基。

合在一起,就是线段树套线性基,类似经典的树套树。

详细思路

线段树大家应该都会,如果不会建议学习一下,这是一个很有用的数据结构。

线性基大家应该都会,如果不会可以看 这篇博客

首先,每一个线段树节点,都保存一个线性基。(单个线性基空间复杂度为 \(O(\log\max\{x\})\),是可以接受的,不用担心会MLE)

首先,对于修改操作,我们不方便 \(\operatorname{pushup}\),那么我们可以想到一个更好的方法:就是我们线段树DFS到的每一个区间节点都包含着修改值,那么我们考虑像权值线段树那样,经过一个点都把修改的元素插入节点线性基。

查询,我们可以考虑实现一个操作 \(\operatorname{expand}\),表示用一个新的线性基扩展原来的线性基(说人话:将另一个线性基的所有元素都插入原来的线性基)

\(\operatorname{expand}\) 操作有一个简单有效的优化常数的方法,就是遍历线性基数组时,仅插入非 \(0\) 值。

然后,我们就可以像经典的线段树那样实现,只不过将维护信息并的运算符换成 \(\operatorname{expand}\) 即可。

(注:有的同学可能习惯将我的 \(\operatorname{expand}\) 操作换成类似线性基加法的 \(\operatorname{merge}\),这一点看大家个人喜好)

时间复杂度 \(O(n\log m\log^{2}\max\{x\})\),空间复杂度 \(O(n\log\max\{x\})\),可以通过本题。

代码

#include <bits/stdc++.h>
#define int long long
using namespace std; namespace Basis{
const int MAX_BIT = 60;
struct Basis{
int p[MAX_BIT+5];
int _how_many_numbers_can_xor;
void clear(){
memset(p,0,sizeof(p));
_how_many_numbers_can_xor=0;
}
Basis(){
clear();
}
void insert(int x){
for(int i=MAX_BIT;i>=0;i--){
if(!(x>>i))continue;
if(!p[i]){
p[i]=x;
_how_many_numbers_can_xor++;
break;
}
x^=p[i];
}
}
int max_xor(){
int ans=0;
for(int i=MAX_BIT;i>=0;i--){
if((ans^p[i])>ans){
ans^=p[i];
}
}
return ans;
}
bool can_be_xor(int x){
for(int i=MAX_BIT;i>=0;i--){
if(x&(1ll<<i))x^=p[i];
}
return x==0;
}
int numbers_can_xor(){
return (1ll<<_how_many_numbers_can_xor);
}
void expand(Basis &x){
for(int i=MAX_BIT;i>=0;i--){
if(x.p[i]){
insert(x.p[i]);
}
}
}
};
} namespace sgt{
Basis::Basis t[200005];
void update(int x,int v,int i,int l,int r){
t[i].insert(v);
if(l==r){
return;
}
int mid=(l+r)>>1;
if(x<=mid){
update(x,v,i<<1,l,mid);
}
else{
update(x,v,i<<1|1,mid+1,r);
}
}
Basis::Basis result;
void query(int ql,int qr,int i,int l,int r){
if(ql<=l&&qr>=r){
result.expand(t[i]);
return;
}
int mid=(l+r)>>1;
if(ql<=mid){
query(ql,qr,i<<1,l,mid);
}
if(qr>mid){
query(ql,qr,i<<1|1,mid+1,r);
}
}
} int n,m; signed main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>n>>m;
while(n--){
int op,a,b;
cin>>op>>a>>b;
if(op==1){
sgt::update(a,b,1,1,m);
}
else{
sgt::result.clear();
sgt::query(a,b,1,1,m);
cout<<sgt::result.max_xor()<<'\n';
}
}
return 0;
}

加强版:P5607 [Ynoi2013] 无力回天 NOI2017

如果将单点修改变成区间修改,那么应该如何处理呢?可以思考一下。(提示:想想差分)

P5607 [Ynoi2013] 无力回天 NOI2017 题解

线段树套线性基——题解P4839 P哥的桶的更多相关文章

  1. BZOJ.4184.shallot(线段树分治 线性基)

    BZOJ 裸的线段树分治+线性基,就是跑的巨慢_(:з」∠)_ . 不知道他们都写的什么=-= //41652kb 11920ms #include <map> #include < ...

  2. bzoj 4184: shallot (线段树维护线性基)

    题面 \(solution:\) 这一题绝对算的上是一道经典的例题,它向我们诠释了一种新的线段树维护方式(神犇可以跳过了).像这一类需要加入又需要维护删除的问题,我们曾经是遇到过的像莫对,线段树... ...

  3. $CF938G\ Shortest\ Path\ Queries$ 线段树分治+线性基

    正解:线段树分治+线性基 解题报告: 传送门$QwQ$ 考虑如果只有操作3,就这题嘛$QwQ$ 欧克然后现在考虑加上了操作一操作二 于是就线段树分治鸭 首先线段树叶子节点是询问嘛这个不用说$QwQ$. ...

  4. 【BZOJ4184】shallot 线段树+vector+线性基

    [BZOJ4184]shallot Description 小苗去市场上买了一捆小葱苗,她突然一时兴起,于是她在每颗小葱苗上写上一个数字,然后把小葱叫过来玩游戏. 每个时刻她会给小葱一颗小葱苗或者是从 ...

  5. 2017 ICPC西安区域赛 A - XOR (线段树并线性基)

    链接:https://nanti.jisuanke.com/t/A1607 题面:   Consider an array AA with n elements . Each of its eleme ...

  6. 【luogu3733】【HAOI2017】 八纵八横 (线段树分治+线性基)

    Descroption 原题链接 给你一个\(n\)个点的图,有重边有自环保证连通,最开始有\(m\)条固定的边,要求你支持加边删边改边(均不涉及最初的\(m\)条边),每一次操作都求出图中经过\(1 ...

  7. LOJ 2312(洛谷 3733) 「HAOI2017」八纵八横——线段树分治+线性基+bitset

    题目:https://loj.ac/problem/2312 https://www.luogu.org/problemnew/show/P3733 原本以为要线段树分治+LCT,查了查发现环上的值直 ...

  8. BZOJ4184:shallot(线段树分治,线性基)

    Description 小苗去市场上买了一捆小葱苗,她突然一时兴起,于是她在每颗小葱苗上写上一个数字,然后把小葱叫过来玩游戏. 每个时刻她会给小葱一颗小葱苗或者是从小葱手里拿走一颗小葱苗,并且 让小葱 ...

  9. 2017西安区域赛A / UVALive - 8512 线段树维护线性基合并

    题意:给定\(a[1...n]\),\(Q\)次询问求\(A[L...R]\)的异或组合再或上\(K\)的最大值 本题是2017的西安区域赛A题,了解线性基之后你会发现这根本就是套路题.. 只要用线段 ...

  10. 【线段树分治 线性基】luoguP3733 [HAOI2017]八纵八横

    不知道为什么bzoj没有HAOI2017 题目描述 Anihc国有n个城市,这n个城市从1~n编号,1号城市为首都.城市间初始时有m条高速公路,每条高速公路都有一个非负整数的经济影响因子,每条高速公路 ...

随机推荐

  1. 现有一个接口DataOperation定义了排序方法sort(int[])和查找方法search(int[],int),已知类QuickSort的quickSort(int[])方法实现了快速排序算法

    欢迎大家加入我的社区:http://t.csdn.cn/Q52km 社区中不定时发红包 文章目录 1.UML类图 2.源码: 3.优缺点分析 1.UML类图 2.源码: package com.bac ...

  2. 一篇文章带你了解服务器操作系统——Linux简单入门

    一篇文章带你了解服务器操作系统--Linux简单入门 Linux作为服务器的常用操作系统,身为工作人员自然是要有所了解的 在本篇中我们会简单介绍Linux的特点,安装,相关指令使用以及内部程序的安装等 ...

  3. Ubuntu编译安装php7.4

    Ubuntu编译安装php7.4  [root@ubuntu2004 php-7.4.30]#apt install gcc libssl-dev libxml2-dev libsqlite3-dev ...

  4. 详解pyautogui模块

    一.安装 pip install pyautogui 或者 pip install -i  https://pypi.tuna.tsinghua.edu.cn/simple pyautogui 二.全 ...

  5. docker支持ipv6

    方法 方法一.Pv6地址 不为容器中的服务特别分配IPv6地址. 只要Docker把外部的IPv6地址端口映射到容器的IPv4端口上,随后访问主机的IPv6相应端口即可. 方法二.为Docker网络分 ...

  6. DevOps | 企业内源(内部开源)适合什么样的公司

    框架类是否适合企业内源? 框架类都由公司早期来的一些大佬们负责(相当于技术委员会),更新频率非常低.给框架类提MR的人,多数本身就在技术委员会. 如果公司的人员众多,类似BAT级别,几万人使用的框架, ...

  7. RocketMQ 在同程旅行的落地实践

    本文作者:刘树东 - 同程艺龙技术专家 01/使用概况 同程旅行选择RocketMQ主要基于以下几个方面的考虑: 技术栈:公司主要以 Java 开发为主,因此我们倾向于选择一款用 Java 实现的MQ ...

  8. 修改input标签里面的提示文字(placeholder)的样式

    使用 ::-webkit-input-placeholder 伪类 input::-webkit-input-placeholder{ // 修改字体大小 font-size:12px; // 修改文 ...

  9. Go语言核心36讲06

    我已经为你打开了Go语言编程之门,并向你展示了"程序从初建到拆分,再到模块化"的基本演化路径. 一个编程老手让程序完成基本演化,可能也就需要几十分钟甚至十几分钟,因为他们一开始就会 ...

  10. 【云原生 · Kubernetes】Taint和Toleration(污点和容忍)

    个人名片: 因为云计算成为了监控工程师‍ 个人博客:念舒_C.ying CSDN主页️:念舒_C.ying Taint和Toleration(污点和容忍) 概念 添加多个tainit(污点) 使用例子 ...