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的更多相关文章

  1. CodeForces - 1100F:Ivan and Burgers (线性基&贪心)(离线 在线)

    题意:给定N个数,Q次询问,求区间最大异或和. 思路:一开始想的线性基+线段树.单次线性基合并的复杂度为20*20,结合线段树,复杂度为O(NlogN*20*20):显然,超时. 超时代码: #inc ...

  2. HDU6579 2019HDU多校训练赛第一场1002 (线性基)

    HDU6579 2019HDU多校训练赛第一场1002 (线性基) 传送门:http://acm.hdu.edu.cn/showproblem.php?pid=6579 题意: 两种操作 1.在序列末 ...

  3. codeforces 1101G (Zero XOR Subset)-less 前缀异或+线性基

    题目传送门 题意:给出一个序列,试将其划分为尽可能多的非空子段,满足每一个元素出现且仅出现在其中一个子段中,且在这些子段中任取若干子段,它们包含的所有数的异或和不能为0. 思路:先处理出前缀异或,这样 ...

  4. [2019杭电多校第一场][hdu6579]Operation(线性基)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6579 题目大意是两个操作,1个是求[l,r]区间子序列的最大异或和,另一个是在最后面添加一个数. 如果 ...

  5. 2019杭电多校第一场hdu6579 Operation(线性基)

    Operation 题目传送门 解题思路 把右边的数尽量往高位放,构造线性基的时候同时记录其在原序列中的位置,在可以插入的时候如果那个位置上存在的数字的位置比新放入的要小,就把旧的往后挤.用这种发现构 ...

  6. Codeforces1101G (Zero XOR Subset)-less 【线性基】【贪心】

    题目分析: 考虑到这是一个区间的异或问题,不妨求出前缀和,令$sum[i] = Xor_{j=1}^{i}a[j]$. 对于区间$[l,r]$的异或结果,等于$sum[r] \oplus sum[l- ...

  7. CF1101G (Zero XOR Subset)-less 线性基

    传送门 既然每一次选择出来的都是一个子段,不难想到前缀和计算(然而我没有想到--) 设异或前缀和为\(x_i\),假设我们选出来的子段为\([1,i_1],(i_1,i_2],...,(i_{k-1} ...

  8. bzoj 2115 Xor - 线性基 - 贪心

    题目传送门 这是个通往vjudge的虫洞 这是个通往bzoj的虫洞 题目大意 问点$1$到点$n$的最大异或路径. 因为重复走一条边后,它的贡献会被消去.所以这条路径中有贡献的边可以看成是一条$1$到 ...

  9. ACM线性基学习笔记

    https://www.cnblogs.com/31415926535x/p/11260897.html 概述 最近的几场多校出现了好几次线性基的题目,,会想起之前在尝试西安区域赛的一道区间异或和最大 ...

随机推荐

  1. centos 6.5 nat方式上网络设置

    1 前提虚拟机采用nat的方式和主机进行通信,这个时候再电脑上会模拟一个vmnet8网卡,如果是host-only对应的是vmnet1,配置一样 vmnet8的虚拟网卡,虚拟机通过vmnet8和主机之 ...

  2. ant+jmeter+jenkins接口自动化测试一

    [Jmeter篇]jmeter+Ant+Jenkins接口自动化测试集成(一) 橙子探索测试发表于橙子探索测试订阅 90 一.简介 1.什么是ant? ant是构建工具,把代码从某个地方拿来,编译,再 ...

  3. JavaScript 格式化数字、金额、千分位、保留几位小数、舍入舍去…

    JavaScript 格式化数字.金额.千分位.保留几位小数.舍入舍去… 类库推荐 1. Numeral.js 一个用于格式化和操作数字的JavaScript库.数字可以被格式化为货币,百分比,时间, ...

  4. Redhat FreeIPA Server 安装服务端和客户端 (实验:VMware环境下)

    实验环境:windows7 + vmware 15 + redhat 71:准备2台虚拟机:      虚拟机VMnet8,Subnet IP:192.168.145.0      Redhat 7( ...

  5. SSM中保存数据出现415错误

    服务器415错误 ssm框架的controller jsp页面 问题:页面出现415错误 原因:请求和响应类型不一致 分析: 先排除以下基本的环境配置 1.URL路径对应好,视图解析器配置好,cont ...

  6. 【秒懂Java】【第1章_初识Java】02_软件开发

    通过上一篇文章<01_编程语言>,我们了解到 Java是众多编程语言中的其中一种 编程语言可以用来开发软件 因此,我们即将要学习的Java技术,是属于软件开发的范畴.那软件开发的前景如何呢 ...

  7. python检测“无内容”图片

    思路1:通过图像熵检测,“无内容”图像熵较小,可通过设置阈值检测“无内容”图像,计算图像熵可参考:https://www.cnblogs.com/niulang/p/12195152.html 思路2 ...

  8. 利用oracle数据库闪回功能将oracle数据库按时间点恢复

    oracle更新脚本把原数据冲了,并且没有备份,急煞我也         解决办法:         oracle数据库有闪回功能:   select * from tab 可以查出已被删除的表    ...

  9. 自适应高度输入框(contenteditable/textarea)

      一.用div模拟textarea div模拟输入域可以根据输入内容自动伸缩,而input和textarea输入内容较多时,高度固定,内容会显示不全. 1.坑1(IOS端无法输入) 在取消全局默认样 ...

  10. sql语句-CASE WHEN用法详解

    当我们需要从数据源上 直接判断数据显示代表的含义的时候 ,就可以在SQL语句中使用 Case When这个函数了. Case具有两种格式.简单Case函数和Case搜索函数. 第一种 格式 : 简单C ...