前缀和线性基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 概述 最近的几场多校出现了好几次线性基的题目,,会想起之前在尝试西安区域赛的一道区间异或和最大 ...
随机推荐
- Python实用笔记 (14)函数式编程——匿名函数
当我们在传入函数时,有些时候,不需要显式地定义函数,直接传入匿名函数更方便. 在Python中,对匿名函数提供了有限支持.还是以map()函数为例,计算f(x)=x2时,除了定义一个f(x)的函数外, ...
- 【总结-前台发送后台接收表单】MVC提交表单的四种方式
https://www.cnblogs.com/chenwolong/p/Form.html#commentform 后台控制器接收前台表单参数三种方法: 一.普通参数 HTML标签name 和参数名 ...
- EntityFramework Core 迁移忽略主外键关系
前言 本文来源于一位公众号童鞋私信我的问题,在我若加思索后给出了其中一种方案,在此之前我也思考过这个问题,借此机会我稍微看了下,目前能够想到的也只是本文所述方案. 为何要忽略主外键关系 我们不仅疑惑为 ...
- Zookeeper-Access Control List(ACL)
概述 Z K作为一个分布式协调框架.内部存储着一些分布式系统运行时状态的元数据.如何有效的保护这些数据的安全.如何做一个比较好的权限控制显得非常的重要. ZK 为我们提供一套完善的 ACL(acces ...
- Volatile关键字的解读
原子性 定义: 在Java中,对基本数据类型的变量的读取和赋值操作是原子性操作,即这些操作是不可被中断的,要么执行,要么不执行. Java内存模型只保证了基本读取和赋值是原子性操作,如果要实现更大范围 ...
- 多线程01-CAS (CompareAndSwap)
1.基本概念 原子性是不可中断的最小操作:在Java中,一般通过加锁或者自旋CAS方式来确保原子操作: 而CAS(compareAnd swap)作为Java中常用的保证原子性的手段,JDK1.5之后 ...
- Java入门系列之访问修饰符作用范围
前言 之前以为Java和C#中访问修饰符差不多一样,后面才了解到还是有些差异,本节只讲解学习Java中访问修饰符一些需要注意的地方或者从概念上不太好理解我们会通过实际例子来说明,若有错误之处,还请批评 ...
- 二分查找&二叉排序树
首先我们先来复习一下二分查找的算法 对于正向序列的二分查找 递归实现: bool binary_search(vector<int> &sort_arry,int begin,in ...
- MySQL 对window函数执行sum函数疑似Bug
MySQL 对window函数执行sum函数疑似Bug 使用MySql的窗口函数统计数据时,发现一个小的问题,与大家一起探讨下. 环境配置: mysql-installer-community-8.0 ...
- day18 装饰器(下)+迭代器+生成器
目录 一.有参装饰器 1 前提 2 如何使用有参装饰器 3 有参装饰器模板 4 修正装饰器 二.迭代器 1 什么是迭代器 2 为什么要有迭代器 3 如何用迭代器 3.1 可迭代对象 3.2 可迭代对象 ...