Xor Query [ABC223H]
https://atcoder.jp/contests/abc223/tasks/abc223_h
题解
奇技淫巧。。。
首先当然是想到了线性基 但是区间的限制怎么办呢?
考虑固定右端点,对于线性基的每一位记录一个 表示这一位的值是从 来的
每次加入一个 时,从大到小枚举第 位,如果 的第 位为 :
如果线性基的第 位没有值就把它设为 并且跳出循环
否则如果 就交换 ,交换线性基第 位的值和 ,然后继续枚举低位
查询时只需要保证所有需要修改的位 都满足 即可
实现和普通的异或线性基差别不大 见代码
由于此篇题解比较垃圾所以没有证明,只是记录一下这个技巧(狗头)
#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;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现