HDU6579系列题解

本文介绍了如何使用线性基解决在线操作数列并查询子集异或最大值的问题,包括在数列末尾插入数和区间查询。通过改变线性基的构造策略,可以有效地避免区间外的干扰,实现复杂度为O((n + m) logx)的解法。同时,还探讨了离线操作的情况,并提到了线段树在处理更复杂问题时的应用。
摘要由CSDN通过智能技术生成

题目链接

题目大意:

给你一个长度为n的数列,有m次操作,操作有两种:

  1. 在数列末尾插入一个数
  2. 查询区间的子集异或最大值

操作强制在线,n ≤ \le 5e5,m ≤ \le 5e5,所有数值域[0, 2 30 2^{30} 230]。

难度:Ag

分析:

线性基可以处理的操作是:

  1. 在数列末尾插入一个数
  2. 查询全局的子集异或最大值

由于线性基的长度很短,因此我们可以将数列所有前缀的线性基保存下来。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为值域大小。

代码:

# include <bits/stdc++.h>
# define MAXN 1000005
# define MAXM 35

using namespace std;

struct LB
{
   
	int n;	//当前已插入的数字个数
	int a[MAXN][MAXM];	//保存所有前缀区间的线性基
	int b[MAXN][MAXM
  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值