整理的算法模板合集: ACM模板

点我看算法全家桶系列!!!

实际上是一个全新的精炼模板整合计划


题目传送门

Problem

给你 nnn 和 nnn 个整数的数组 aaa,以及kkk和qqq,有 qqq 次询问,每次询问输入两个整数l,rl,rl,r,表示区间[l,r][l,r][l,r],要你每次在这个区间里选择若干个数,使得这些数的异或和sumsumsum,再按位或kkk的值最大,即求最大的res = sum | k

其中0≤ai≤108,1≤N≤10000,1≤Q≤100000,0≤K≤1000000 \le a_i \le 10^8,1≤N≤10000, 1≤Q≤100000, 0≤K≤1000000≤ai​≤108,1≤N≤10000,1≤Q≤100000,0≤K≤100000。

Solution

首先我们本题需要的一个操作就是在 nnn 个数里,选择若干个数,使得他们的异或和最大,很明显,这个就是线性基的基本操作。

  • 区间操作 —— 线段树
  • 异或操作 —— 线性基

所以我们可以考虑一下线性基。

然后分析题意,发现要求的答案是 sum | k 最大,而不是单纯的最大的 sum 。所以来思考一下,最大的 sum 是不是最大的 res = sum | k 呢?

举个栗子:

max_sum(2)=10000max\_sum_{(2)} = 10000max_sum(2)​=10000

k(2)=10000k_{(2)} = 10000k(2)​=10000

(max_sum∣k)(2)=10000=24=16(max\_sum | k)_{(2)} = 10000 = 2^4=16(max_sum∣k)(2)​=10000=24=16

而我们的线性基实际上可以线性表出一个数x=1111x=1111x=1111,因为 xxx不是最大的异或和,所以我们直接线性基求 max_summax\_summax_sum是得不到 xxx 的,但是(k∣x)(2)=11111=31(k|x)_{(2)}=11111=31(k∣x)(2)​=11111=31明显大于 161616。

我们发现按位或运算,只要有一个1就行了,两个1和一个1没有区别,所以对于k中是1 的所有位(二进制下),线性基得到的sumsumsum,都没必要是1,所以我们可以把整个a数组的k是1的那一位全部变成0,这样相当于把a数组,每个数看成一个二进制下的向量组成的向量组的线性空间的线性基的维数减少了,也就是这个线性空间的极大线性无关向量组的向量个数减少了,删掉了我们不需要的1,因为这些1存在在这个线性基里时,会导致最大异或和更大,但是这个很大的数对我们最终的答案没有贡献。

也就是按位或运算,是两个数的二进制中,对应位只要有 111 ,那么就是该位结果就是 111 ,所以要想 kkk 按位或运算后的结果尽量大,就需要异或出的数,各个位上的 111 尽量多。

所以我们可以将 kkk 取反,然后把所有数在加入线性基之前,全部 按位异或运算一遍,这样把没用的1全部删掉,再加入线性基。

这样,这个线性空间中的线性基的这个极大线性无关向量组中的每一位,全部都是能使得 kkk 变大的数了,因为 kkk 的二进制上的每一位 111 的位置,线性基中都是000,而 kkk 的二进制上的每一位 000 的位置,线性基中可能是111,这样我们此时线性基得到的最大的异或和

所以,最终的答案就是 k | sumsum 是修改后的区间的数插入线性基的最大异或和。

我们使用线段树维护区间操作即可。实际上就是把线段树权值换成当前区间的线性基,简单维护一下即可。

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <map>
#include <queue>
using namespace std;
typedef long long ll;
typedef int itn;
typedef pair<int, int>PII;
const int N = 50007, mod = 1e9 + 7, INF = 2.1e9;
const double eps = 1e-8;
const int Base = 27 * 2;//线性基数组大小,开大一点,嘻嘻嘻
//s < 2 ^ {63} - 1
//说明线性基最多有62个向量struct LinearBase
{int dimension = 27; // dimension 维数,就是线性基的维数 = logs, (s为元素最大值)//dimension一定要是logs,错一点就会WA呜呜呜//线性基数组ll a[Base + 7];//注意这里要加一点,因为下面的循环也是这个数LinearBase() {fill(a, a + Base + 7, 0);}LinearBase(ll *x, int n) {build(x, n);}void insert(ll t){// 逆序枚举二进制位for(int i = dimension; i >= 0; -- i) {if(t == 0) return ;// 如果 t 的第 i 位为 0,则跳过if(!(t >> i & 1)) continue;// 如果 a[i] != 0,则用 a[i] 消去 t 的第 i 位上的 1if(a[i]) t ^= a[i];else {// 找到可以插入 a[i] 的位置// 用 a[0...i - 1] 消去 t 的第 [0, i) 位上的 1// 如果某一个 a[k] = 0 也无须担心,因为这时候第 k 位//不存在于线性基中,不需要保证 t 的第 k 位为 0for(int k = 0; k < i; ++ k)if(t >> k & 1) t ^= a[k];// 用 t 消去 a[i + 1...L] 的第 i 位上的 1for(int k = i + 1; k <= dimension; ++ k)if(a[k] >> i & 1) a[k] ^= t;// 插入到 a[j] 的位置上a[i] = t;break;}// 此时 t 的第 i 位为 0,继续寻找其最高位上的 1}// 如果没有插入到任何一个位置上,则表明 t 可以由 a 中若干个元素的异或和表示出,即 t 在 span(a) 中}// 数组 x 表示集合 S,下标范围 [1...n]void build(ll *x, int n){fill(a, a + Base + 7, 0);for(int i = 1; i <= n; ++ i)insert(x[i]);}ll query_max(){ll res = 0;for(int i = 0; i <= dimension; ++ i)res ^= a[i];return res;}void mergefrom(const LinearBase &other) {for(int i = 0; i <= dimension; ++ i)insert(other.a[i]);}static LinearBase merge(const LinearBase &a, const LinearBase &b) {LinearBase res = a;for(int i = 0; i <= 27; ++ i)res.insert(b.a[i]);return res;}
};int n, m, t, q, k;
ll a[N];struct Tree
{int l, r;LinearBase elem;//element
}tr[N];void build(int p, int l, int r)
{tr[p] = {l, r};if(l == r) {tr[p].elem.insert(a[r]);return ;}int mid = (l + r) >> 1;build(p << 1, l, mid);build(p << 1 | 1, mid + 1, r);tr[p].elem = tr[p].elem.merge(tr[p << 1].elem, tr[p << 1 | 1].elem);
}LinearBase query(int p, int l, int r)
{if(l <= tr[p].l && tr[p].r <= r)return tr[p].elem;int mid = (tr[p].l + tr[p].r) >> 1;LinearBase res;if(l <= mid) res = res.merge(res, query(p << 1, l, r));if(r > mid) res = res.merge(res, query(p << 1 | 1, l, r));return res;
}int main()
{scanf("%d", &t);while(t -- ) {scanf("%d%d%d", &n, &q, &k);for(int i = 1; i <= n; ++ i) {scanf("%lld", &a[i]);/*k的存在会对求线性基最大值时的主元产生影响,所以预处理一下,a[i]只保留k为0的位,这样贡献最大*/for(int j = 0; j < 27; ++ j) {if((k >> j & 1) && (a[i] >> j & 1))a[i] ^= (1 << j);}}build(1, 1, n);while(q -- ) {int l, r;scanf("%d%d", &l, &r);LinearBase res = query(1, l, r);printf("%lld\n", res.query_max() | k);}}return 0;
}

2017年ICPC西安邀请赛A、XOR(线段树套线性基 + 思维)相关推荐

  1. 2017 ICPC西安区域赛 A - XOR ,线段树合并线性基

    题目链接:A - XOR 题意;给个数组,每次询问一个区间你可以挑任意个数的数字异或和 然后在或上k的最大值 题解:线性基不知道的先看这个,一个线性基可以log的求最大值把对应去区间的线性基求出来然后 ...

  2. BZOJ.4184.shallot(线段树分治 线性基)

    BZOJ 裸的线段树分治+线性基,就是跑的巨慢_(:з」∠)_ . 不知道他们都写的什么=-= //41652kb 11920ms #include <map> #include < ...

  3. 2017 ICPC西安区域赛 A - XOR (线段树并线性基)

    链接:https://nanti.jisuanke.com/t/A1607 题面: Consider an array AA with n elements . Each of its element ...

  4. 【线段树分治 线性基】luoguP3733 [HAOI2017]八纵八横

    不知道为什么bzoj没有HAOI2017 题目描述 Anihc国有n个城市,这n个城市从1~n编号,1号城市为首都.城市间初始时有m条高速公路,每条高速公路都有一个非负整数的经济影响因子,每条高速公路 ...

  5. P3292 [SCOI2016]幸运数字(树剖 + 线段树维护线性基)

    P3292 [SCOI2016]幸运数字 思路 如果这题是求x,yx, yx,y之间的距离显然我们可以通过树剖加线段树来写, 但是这里变成了求任意个数的异或最大值.如果给定区间我们显然可以通过线性基来 ...

  6. UVALive - 8512——线段树维护线性基

    [题目描述] UVALive - 8512XOR [题目分析] 这种区间+线性基的问题我们可以考虑用线段树维护,线性基的合并的话就直接暴力合并 找到所在区间的线性基后再查找最大的数,我看网上的博客要说 ...

  7. bzoj 4184 shallot 时间线建线段树+vector+线性基

    题目大意 n个时间点 每个时间点可以插入一个权值或删除一个权值 求每个时间点结束后异或最大值 分析 异或最大值用线性基 但是线性基并不支持删除操作 我们可以对时间线建一棵线段树 离线搞出每个权值出现的 ...

  8. LOJ 2312(洛谷 3733) 「HAOI2017」八纵八横——线段树分治+线性基+bitset

    题目:https://loj.ac/problem/2312 https://www.luogu.org/problemnew/show/P3733 原本以为要线段树分治+LCT,查了查发现环上的值直 ...

  9. 【BZOJ4184】shallot 线段树+vector+线性基

    [BZOJ4184]shallot Description 小苗去市场上买了一捆小葱苗,她突然一时兴起,于是她在每颗小葱苗上写上一个数字,然后把小葱叫过来玩游戏. 每个时刻她会给小葱一颗小葱苗或者是从 ...

最新文章

  1. 【冷知识】获取网页所有的监听事件类型、方法。请认准getEventListeners
  2. C++中如何访问全局变量和全局函数
  3. Maven提高篇系列之(五)——处理依赖冲突
  4. Struts2是什么?Struts2的优势有哪些?
  5. Docker shipyard 试用
  6. [js] localStorage什么时候过期?
  7. Tomcat服务器响应特别慢(服务器假死)的解决办法
  8. jquery中ajax请求分类
  9. linux浮动ip添加 手动,在Linux 双机下自己手动实现浮动ip技术
  10. linux常用文本编缉命令(strings/sed/awk/cut/uniq/sort)
  11. SQLServer之删除用户自定义数据库用户
  12. 移动通信matlab实现,现代移动通信中的调制技术研究及Matlab实现
  13. 湖大离散数学实验代码汇总
  14. Wretch超雅虎奇摩成台湾省第一大网站
  15. zookeeper storm kafka开机简易启动脚本
  16. android多个switch可,能刷安卓,任天堂 Switch 再跑个 Win10 如何?
  17. sharding-jdbc 分库分表的 4种分片策略
  18. Java线程(五):Executors、ThreadFactory
  19. DOM解析与DOM4J
  20. vue 点击打开小窗口

热门文章

  1. 树莓派安装openCV做图像识别
  2. 每日一题(合并表格)
  3. new File(String Path)加载资源问题
  4. openchain 环境部署
  5. 持续集成(三):最佳实践
  6. 前端CSS预处理器Sass
  7. Weblogic集群配置__部署润乾应用
  8. nodeJs-autoMerge
  9. Java反射机制分析指南
  10. 《网管员必读》学习笔记之DNS服务器的安装与配置