前缀和线性基HDU6579
Operation

题解:看到区间最大异或和,首先想到的是线性基;
线性基可以处理的操作是:
- 在数列末尾插入一个数
- 查询全局的子集异或最大值
由于线性基的长度很短,因此我们可以将数列所有前缀的线性基保存下来。1到x的线性基可以由1到x-1的线性基通过插入a[x]来求得,这样,我们就可以查询前缀区间的子集异或最大值。现在问题的关键在于,查询区间 [L, R] 时,如何避免 [1, L-1] 的干扰。
考虑线性基的插入过程,如果线性基当前位上已经有值,我们就不能把待插入的值放入这一位,因此线性基上每一位的数,都是对应位上在原数列最左侧的数字。现在我们改变策略,使得线性基上每一位的数,都变成对应位上在原数列最右侧的数字。实现这个策略的方法是:我们额外保存线性基上每一位数在原数列中的位置,插入的时候,如果对应位上的数在原数列中更靠左,就用待插入的数和它交换。基于这种策略,我们在查询区间 [L, R] 时,可以在区间 [1, R] 对应的线性基中查询,对于线性基上每一位的数,如果它在原数组中出现的位置比 L 更靠右,就考虑它对答案的贡献,否则直接跳过这一位。
这个做法的正确性也很显然,通过改变策略,使线性基上每一位数变成对应位上在原数列最右侧的数字,可以看成线性基插入数字的顺序变反,完全不影响线性基的性质。同时,将线性基上所有在原数组中的位置比 x 更靠左的数字删除,可以视为区间 [1, L-1] 的数字还没有被插入线性基。
复杂度:O((n + m) logx),n为初始数列长度,m为操作次数,x为值域大小。
大佬的博客讲解:here
AC_Code:
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
typedef long long ll;
#define endl '\n'
const int maxn = ;
const int maxm = 5e5+;
const int inf = 0x3f3f3f3f; int cnt;//当前已插入的数的个数
int a[maxm][maxn];//保存所有前缀区间的线性基
int b[maxm][maxn];//保存线性基上的数字在原数组上的对应位置
int n,m; void LB(int x){
int cur=++cnt;//表示待插入的数字在原数组上的位置
for(int i=;i>=;i--){
a[cnt][i]=a[cnt-][i];
b[cnt][i]=b[cnt-][i];
}
for(int i=;i>=;i--){
if( !(x>>i) ) continue;
if( !a[cnt][i] ){
a[cnt][i]=x;
b[cnt][i]=cur;
break;
}
else{
if( cur>b[cnt][i] ){ //如果待插入的数字在原数组上更靠右,则用线性基上的数与其交换
swap(a[cnt][i],x);
swap(b[cnt][i],cur); //位置也要交换
}
x^=a[cnt][i];
}
}
} int query(int l,int r){
l=l%cnt+; r=r%cnt+; //注意这里是%cnt,不是%n
if( l>r ) swap(l,r);
int ret=;
for(int i=;i>=;i--){
if( b[r][i]>=l ){ //如果在原数组中的位置比l更靠右,那么就产生贡献,此处b[r][i]就已经限制了右区间
ret=max(ret,ret^a[r][i]); //线性基贪心求最大值的基本操作
}
}
return ret;
} int main()
{
int t; scanf("%d",&t);
while( t-- ){
cnt=;
scanf("%d%d",&n,&m);
for(int i=;i<n;i++){
int a;
scanf("%d",&a);
LB(a);
}
int lastans=, opt, x, y; //lastans用于处理强制在线
for(int i=;i<m;i++){
scanf("%d%d",&opt,&x);
if( opt== ){
scanf("%d",&y);
x=x^lastans;
y=y^lastans;
lastans = query(x, y);
printf("%d\n",lastans);
}
else{
LB(x^lastans);
}
}
}
return ;
}
前缀和线性基HDU6579的更多相关文章
- CodeForces - 1100F:Ivan and Burgers (线性基&贪心)(离线 在线)
题意:给定N个数,Q次询问,求区间最大异或和. 思路:一开始想的线性基+线段树.单次线性基合并的复杂度为20*20,结合线段树,复杂度为O(NlogN*20*20):显然,超时. 超时代码: #inc ...
- HDU6579 2019HDU多校训练赛第一场1002 (线性基)
HDU6579 2019HDU多校训练赛第一场1002 (线性基) 传送门:http://acm.hdu.edu.cn/showproblem.php?pid=6579 题意: 两种操作 1.在序列末 ...
- codeforces 1101G (Zero XOR Subset)-less 前缀异或+线性基
题目传送门 题意:给出一个序列,试将其划分为尽可能多的非空子段,满足每一个元素出现且仅出现在其中一个子段中,且在这些子段中任取若干子段,它们包含的所有数的异或和不能为0. 思路:先处理出前缀异或,这样 ...
- [2019杭电多校第一场][hdu6579]Operation(线性基)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6579 题目大意是两个操作,1个是求[l,r]区间子序列的最大异或和,另一个是在最后面添加一个数. 如果 ...
- 2019杭电多校第一场hdu6579 Operation(线性基)
Operation 题目传送门 解题思路 把右边的数尽量往高位放,构造线性基的时候同时记录其在原序列中的位置,在可以插入的时候如果那个位置上存在的数字的位置比新放入的要小,就把旧的往后挤.用这种发现构 ...
- Codeforces1101G (Zero XOR Subset)-less 【线性基】【贪心】
题目分析: 考虑到这是一个区间的异或问题,不妨求出前缀和,令$sum[i] = Xor_{j=1}^{i}a[j]$. 对于区间$[l,r]$的异或结果,等于$sum[r] \oplus sum[l- ...
- CF1101G (Zero XOR Subset)-less 线性基
传送门 既然每一次选择出来的都是一个子段,不难想到前缀和计算(然而我没有想到--) 设异或前缀和为\(x_i\),假设我们选出来的子段为\([1,i_1],(i_1,i_2],...,(i_{k-1} ...
- bzoj 2115 Xor - 线性基 - 贪心
题目传送门 这是个通往vjudge的虫洞 这是个通往bzoj的虫洞 题目大意 问点$1$到点$n$的最大异或路径. 因为重复走一条边后,它的贡献会被消去.所以这条路径中有贡献的边可以看成是一条$1$到 ...
- ACM线性基学习笔记
https://www.cnblogs.com/31415926535x/p/11260897.html 概述 最近的几场多校出现了好几次线性基的题目,,会想起之前在尝试西安区域赛的一道区间异或和最大 ...
随机推荐
- 019.Kubernetes二进制集群存储longhorn
一 Longhorn存储部署 1.1 Longhorn概述 Longhorn是用于Kubernetes的开源分布式块存储系统. 提示:更多介绍参考:https://github.com/longhor ...
- JavaScript基础对象创建模式之静态成员(027)
在支持“类”的面向对象语言中,静态成员指的是那些所有实例对象共有的类成员.静态成员实际是是“类”的成员,而非“对象”的成员.所以如果 MathUtils类中有个叫 max()的静态成员方法,那么调用这 ...
- 泊车SLAM文献整理
1. 泊车: 线车位检测 Geometric Features-Based Parking Slot Detection 译文链接:https://blog.csdn.net/djfjkj52/art ...
- 移动端Retina屏boder 1px显示为2px或3px的解决方法
我们在开发移动端web项目时经常遇到设置border:1px,但是显示的边框却为2px或是3px粗细,这是因为设备像素比devicePixelRatio为2或3引起的. 何为“设备像素比deviceP ...
- HDU - 5963 朋友(思维题)
题干 B君在围观一群男生和一群女生玩游戏,具体来说游戏是这样的: 给出一棵n个节点的树,这棵树的每条边有一个权值,这个权值只可能是0或1. 在一局游戏开始时,会确定一个节点作为根.接下来从女生开始,双 ...
- Docker-本地镜像发布到阿里云
1.先生成一个镜像 有两种发法:(1)写DockerFile (2)从容器创建一个新的镜像 docker commit [option] 容器ID 镜像名字:版本号 option 说明 :-a 作者 ...
- Python——查看目录下所有的目录和文件
写程序我们经常会遇到需要遍历某一个目录下的所有文件这个操作,然而python有现成的库,只需要2个循环就可以搞定. import os def all_path(dirname): result = ...
- 3.Unity3d物体操作常用按键
新建一个cube物体.在unity3d界面左上角可以看到红色下划线的五个图标(下面用图标1到5数字表示),分别对应不同功能,这些功能操作物体很常用.下面用cube物体的操作来演示这几个功能. 1.按Q ...
- mybitis下choose..when. otherwise条件不起作用
我的代码如下: <select id="findList" resultType="TyArticle"> SELECT <include r ...
- System.Timers.Timer(定时器)
1.System.Timers命名空间下的Timer类.System.Timers.Timer类:定义一个System.Timers.Timer对象,然后绑定Elapsed事件,通过Start()方法 ...