Xor Query [ABC223H]

https://atcoder.jp/contests/abc223/tasks/abc223_h

题解

奇技淫巧。。。

首先当然是想到了线性基 但是区间的限制怎么办呢?

考虑固定右端点,对于线性基的每一位记录一个 id 表示这一位的值是从 aid 来的

每次加入一个 ai 时,从大到小枚举第 j 位,如果 ai 的第 j 位为 1

如果线性基的第 j 位没有值就把它设为 ai 并且跳出循环

否则如果 idj<i 就交换 idj,i,交换线性基第 j 位的值和 ai ,然后继续枚举低位

查询时只需要保证所有需要修改的位 j 都满足 lidj 即可

实现和普通的异或线性基差别不大 见代码

由于此篇题解比较垃圾所以没有证明,只是记录一下这个技巧(狗头)

#include <bits/stdc++.h>
#define N 400005
using namespace std;
typedef long long ll;

template <typename T>
inline void read(T &num) {
	T x = 0, f = 1; char ch = getchar();
	for (; ch > '9' || ch < '0'; ch = getchar()) if (ch == '-') f = -1;
	for (; ch <= '9' && ch >= '0'; ch = getchar()) x = (x<<1) + (x<<3) + (ch^'0');
	num = x * f;
}

int n, m;
ll a[N][60]; int id[N][60];

inline void upd(ll x, int p) {
	int P = p;
	for (int i = 60; ~i; i--) a[P][i] = a[P-1][i], id[P][i] = id[P-1][i];
	for (int i = 60; ~i; i--) if ((x>>i)&1) {
		if (!a[P][i]) {
			a[P][i] = x; id[P][i] = p; break;
		} else if (p > id[P][i]) {
			swap(a[P][i], x); swap(id[P][i], p);
		}
		x ^= a[P][i];
	}
}

int main() {
	read(n); read(m);
	for (int i = 1; i <= n; i++) {
		ll x; read(x); upd(x, i);
	}
	while (m--) {
		int l, r, ok = 1; ll x; read(l); read(r); read(x);
		for (int i = 60; ~i; i--) if ((x>>i)&1) {
			if (!a[r][i] || id[r][i] < l) { ok = 0; break; }
			else x ^= a[r][i];
		}
		puts(ok?"Yes":"No");
	}
	return 0;
}
posted @   AK_DREAM  阅读(239)  评论(0编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示