线段树套线性基——题解P4839 P哥的桶
文章历史
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哥的桶的更多相关文章
- BZOJ.4184.shallot(线段树分治 线性基)
BZOJ 裸的线段树分治+线性基,就是跑的巨慢_(:з」∠)_ . 不知道他们都写的什么=-= //41652kb 11920ms #include <map> #include < ...
- bzoj 4184: shallot (线段树维护线性基)
题面 \(solution:\) 这一题绝对算的上是一道经典的例题,它向我们诠释了一种新的线段树维护方式(神犇可以跳过了).像这一类需要加入又需要维护删除的问题,我们曾经是遇到过的像莫对,线段树... ...
- $CF938G\ Shortest\ Path\ Queries$ 线段树分治+线性基
正解:线段树分治+线性基 解题报告: 传送门$QwQ$ 考虑如果只有操作3,就这题嘛$QwQ$ 欧克然后现在考虑加上了操作一操作二 于是就线段树分治鸭 首先线段树叶子节点是询问嘛这个不用说$QwQ$. ...
- 【BZOJ4184】shallot 线段树+vector+线性基
[BZOJ4184]shallot Description 小苗去市场上买了一捆小葱苗,她突然一时兴起,于是她在每颗小葱苗上写上一个数字,然后把小葱叫过来玩游戏. 每个时刻她会给小葱一颗小葱苗或者是从 ...
- 2017 ICPC西安区域赛 A - XOR (线段树并线性基)
链接:https://nanti.jisuanke.com/t/A1607 题面: Consider an array AA with n elements . Each of its eleme ...
- 【luogu3733】【HAOI2017】 八纵八横 (线段树分治+线性基)
Descroption 原题链接 给你一个\(n\)个点的图,有重边有自环保证连通,最开始有\(m\)条固定的边,要求你支持加边删边改边(均不涉及最初的\(m\)条边),每一次操作都求出图中经过\(1 ...
- LOJ 2312(洛谷 3733) 「HAOI2017」八纵八横——线段树分治+线性基+bitset
题目:https://loj.ac/problem/2312 https://www.luogu.org/problemnew/show/P3733 原本以为要线段树分治+LCT,查了查发现环上的值直 ...
- BZOJ4184:shallot(线段树分治,线性基)
Description 小苗去市场上买了一捆小葱苗,她突然一时兴起,于是她在每颗小葱苗上写上一个数字,然后把小葱叫过来玩游戏. 每个时刻她会给小葱一颗小葱苗或者是从小葱手里拿走一颗小葱苗,并且 让小葱 ...
- 2017西安区域赛A / UVALive - 8512 线段树维护线性基合并
题意:给定\(a[1...n]\),\(Q\)次询问求\(A[L...R]\)的异或组合再或上\(K\)的最大值 本题是2017的西安区域赛A题,了解线性基之后你会发现这根本就是套路题.. 只要用线段 ...
- 【线段树分治 线性基】luoguP3733 [HAOI2017]八纵八横
不知道为什么bzoj没有HAOI2017 题目描述 Anihc国有n个城市,这n个城市从1~n编号,1号城市为首都.城市间初始时有m条高速公路,每条高速公路都有一个非负整数的经济影响因子,每条高速公路 ...
随机推荐
- Linux实战笔记__Ubuntu20.04上搭建Vulhub漏洞环境
安装python3和pip3 安装docker 安装docker-compose 上传解压vulhub-master.zip 启动漏洞环境 进入某漏洞目录,执行docker-compose up -d ...
- 日志处理logging
前言 什么是日志?有什么作用?日志是跟踪软件运行时所发生的事件的一种方法,简单来说它可以记录某时某刻运行了什么代码,当出现问题时可以方便我们进行定位. 由python内置了一个logging模块,用户 ...
- 一步一图带你深入理解 Linux 虚拟内存管理
写在本文开始之前.... 从本文开始我们就正式开启了 Linux 内核内存管理子系统源码解析系列,笔者还是会秉承之前系列文章的风格,采用一步一图的方式先是详细介绍相关原理,在保证大家清晰理解原理的基础 ...
- ElasticSearch之Quick.ElasticSearch.Furion组件的使用
ElasticSearch 使用说明 本章,我们主要讲解在.Net 中对Quick.ElasticSearch.Furion的使用进行介绍! ElasticSearch 的官方客户端 API 文档地址 ...
- 三十一、kubernetes网络介绍
Kubernetes 网络介绍 Service是Kubernetes的核心概念,通过创建Service,可以为一组具有相同功能的容器应用提供一个统一的入口地址,并且将请求负载分发到后端的各个容器应用上 ...
- 如何使用vscode快速配置C语言环境(简单实用)
需要用到的工具: VSCode(Visual Studio Code) 一.首先打开官网链接,然后根据自己的电脑选择合适的安装程序进行下载. 二.在安装时默认点击下一步,最后记得勾选上添加path到系 ...
- 说说switch关键字
Switch语法 switch作为Java内置关键字,却在项目中真正使用的比较少.关于switch,还是有那么一些奥秘的. 要什么switch,我有if-else 确实,项目中使用switch比较少的 ...
- 嵌入式-C语言基础:字符串比较函数strcmp及其实现
#include<stdio.h> #include <string.h> int mystrcmp(char * p1,char * p2) { int ret=0; if( ...
- 2022春每日一题:Day 36
题目:[JLOI2013]删除物品 直接做显然比较复杂,这个题是说对顶栈,但是可以把两个栈拼在一起,记录一下栈顶的下标,然后这样这题就可以转化为线性上的操作查询了,用树状数组简单维护一下就ok了(某个 ...
- 基于SqlSugar的开发框架循序渐进介绍(22)-- Vue3+TypeScript的前端工作流模块中实现统一的表单编辑和表单详情查看处理
在工作流页面中,除了特定的业务表单信息外,往往也需要同时展示通用申请单的相关信息,因此在页面设计的时候需要使用一些组件化的概念来实现动态的内容展示处理,本篇随笔介绍Vue3+TypeScript+El ...