人生第一道Ynoi,开心

Description

https://www.luogu.com.cn/problem/P5607

Solution

拿到这个题,看了一下,发现询问要求最大异或和,怎么办?

没办法,我只学过线性基,就顺着这个思路硬上吧。

我们开一颗线段树,里面的节点存线性基,那么空间复杂度是\(O(n \log v)\)的

先不管修改操作,那么我们容易分析得到单次查询的复杂度是\(O(\log n \log^2 v)\)

这个复杂度一看就是正解,接着想修改

区间\(\text{xor}\)还得维护线性基???什么鬼???

我们想,区间\(\text{xor}\)在线段树上难以办到,但是单点\(\text{xor}\)很简单

怎么办?

差分啊!!!

但我们怎么差分才能保证正确性呢?

熟知,对于一个数列\(a_n\)

如果我们把它差分,使得\(b_1 = a_1, b_i = a_i \text{xor} a_{i-1} (i>1)\)

那么由线性代数基础知识,数列\(b_n\)的线性基和原数列的线性基是一样的

这启发我们线段树维护差分的线性基,然后再单独维护\(a\),询问时将\(a\)插入线段树查询得到的线性基、

这个\(a\)就很好维护了,直接上线段树或者树状数组维护差分即可

这样,单次修改复杂度为\(O(\log n \log v)\)

Code

#include <cstdio>
#include <iostream>
using namespace std;
const int N = 50010;
int n, m, a[N], b[N], opt, l, r, v;
inline int read() {
int res = 0, flag = 0; char ch = getchar();
for(; !isdigit(ch); ch = getchar()) if(ch == '-') flag = 1;
for(; isdigit(ch); ch = getchar()) res = (res << 1) + (res << 3) + (ch ^ 48);
if(flag) res = ~res + 1;
return res;
}
struct LineBase{
int a[31];
inline void clear() {for(int i = 0; i < 31; ++i) a[i] = 0;}
inline void insert(int x) {
for(int i = 30; i + 1; --i)
if(x & (1 << i))
if(!a[i]) {a[i] = x; break;}
else x ^= a[i];
}
}O;
inline LineBase merge(LineBase x, LineBase y) {
for(int i = 30; i + 1; --i) if(y.a[i]) x.insert(y.a[i]);
return x;
}
struct SegmentTree{
#define lc (k << 1)
#define rc (lc | 1)
#define mid (l + r >> 1)
LineBase tr[N << 2];
inline void update(int k) {tr[k] = merge(tr[lc], tr[rc]);}
inline void build(int k, int l, int r) {
if(l == r) {tr[k].insert(b[l]); return;}
build(lc, l, mid), build(rc, mid + 1, r), update(k);
}
inline void modify(int k, int l, int r, int loc) {
if(l > loc || r < loc) return ;
if(l == r) {tr[k].clear(), tr[k].insert(b[l]); return;}
modify(lc, l, mid, loc), modify(rc, mid + 1, r, loc), update(k);
}
inline LineBase query(int k, int l, int r, int L, int R) {
if(l > R || r < L) return O;
if(L <= l && r <= R) return tr[k];
return merge(query(lc, l, mid, L, R), query(rc, mid + 1, r, L, R));
}
}s;
struct BIT{
#define lowbit(x) (x & -x)
int tr[N];
inline void insert(int x, int v) {for(; x <= n; x += lowbit(x)) tr[x] ^= v;}
inline int query(int x) {int res = 0; for(; x; x -= lowbit(x)) res = res ^ tr[x]; return res;}
}bit;
inline void out(int x) {
int flag = 0;
for(int i = 30; i + 1; --i)
if(flag) printf("%d",((x & (1 << i)) > 0));
else if(x & (1 << i)) printf("1"), flag = 1;
if(!flag) printf("0");
}
int main() {
n = read(), m = read();
for(int i = 1; i <= n; ++i) a[i] = read(), b[i] = a[i] ^ a[i - 1], bit.insert(i, b[i]); b[n + 1] = a[n];
s.build(1, 1, n + 1);
for(int i = 1; i <= m; ++i) {
opt = read(), l = read(), r = read(), v = read();
if(opt == 1) {
b[l] ^= v, b[r + 1] ^= v;
bit.insert(l, v), bit.insert(r + 1, v);
s.modify(1, 1, n + 1, l), s.modify(1, 1, n + 1, r + 1);
}
else {
LineBase ans = s.query(1, 1, n + 1, l + 1, r);
ans.insert(bit.query(l));
for(int j = 30; j + 1; --j) if((ans.a[j] ^ v) > v) v ^= ans.a[j];
printf("%d\n",v);
}
}
return 0;
}

最新文章

  1. 营业额统计(bzoj1588)
  2. iOS一些系统事件的生命周期
  3. C#设计模式——模板方法(Template Method)
  4. JavaScript并非“按值传递”
  5. NOIP 2011 Day 1 部分题解 (Prob#1 and Prob#2)
  6. Mac OS X 中使用SAP GUI的方法
  7. sql关键查询
  8. 解决MYSQL弃用模块错误Deprecated: mysql_query(): The mysql extension is deprecated and will be removed in the future
  9. Java 散知识
  10. 基于etcd的Rabbitmq队列订阅负载均衡
  11. Why Helm? - 每天5分钟玩转 Docker 容器技术(160)
  12. [Swift]LeetCode1036.逃离大迷宫 | Escape a Large Maze
  13. 序列化 java.io.Serializable
  14. spring 整合
  15. LINUX 内存使用情况
  16. awk中使用shell的环境变量
  17. 用GridLayout实现计算器的布局
  18. makefile 中wildcard
  19. 数据仓库基础(十)Informatica 组件1
  20. Golang cron 定时任务使用

热门文章

  1. js实现全屏弹框
  2. 记一次 .NET 某工控自动化控制系统 卡死分析
  3. 【原创】Magisk+Shamiko过APP ROOT检测
  4. ASP.NET Core 6框架揭秘实例演示[32]:错误页面的集中呈现方式
  5. Spring源码 04 IOC XML方式
  6. MySQL 数据查询语句
  7. Python自学教程1-安装pycharm和执行环境
  8. [Blender] Blender 获取 Instance 的信息
  9. 你言我语 By Twikoo
  10. CF1368G Shifting Dominoes (线段树)