异或粽子
题面
题解
将题意转化一下就是,对于一个大小为 \(n\) 的数组,求出前 \(k\) 大的不重复的区间异或和的和。
我们记录一下区间前缀异或和。那么一个区间的异或和就可以表示为 \(sum[r]\ xor\ sum[l - 1]\)。
那么我们要求的就是形如这样的最大的 \(k\) 对异或值的和。即 \(sum[i]\ xor\ sum[j] (0\leq j < i \leq n)\)。
也就是在一个大小为 \(n + 1\) 的数组中的 \(\frac{n(n +1)}{2}\) 中组合中选出前 \(k\) 大的。
而这些组合以 \(i, j\) 为长宽的话,对应着一个矩形的情况,而在上述的范围中是一个不包含对角线的类似于三角形的形状。
为了使我们寻找更方便,又因为 \(sum[i]\ xor\ sum[j] = sum[j] \ xor \ sum[i]\) 所以我们可以将另一半补全,寻找两部分中前 \(2k\) 大的值,而对角线上的值显然是 \(0\) 因为答案保证了 \(k \leq \frac{n(n - 1)}{2}\),所以对角线上的值不可能被选择,所以我们可以直接将矩阵补全,所以就不用考虑 \(i, j\) 之间的关系了。
建立一个 \(Trie\) 树,维护某个数与集合中的某个数排名为 \(rk\) 的异或值。
建立一个大根堆,将 \(0\) ~ \(n\) 的数与集合中的某个数排名为 \(1\) 的异或值,即它的排名插入堆中。
每次取出堆顶,将当前排名的下一个排名插入堆中,取完 \(2k\) 个元素后就得到了前 \(2k\) 大的元素。
因为每次插入堆中的都是每个元素与其它元素的组合中未被选择的最大异或值,而大根堆维护了这些组合中的最大值,所以取完 \(2k\) 个元素后就得到了前 \(2k\) 大的元素。
代码
#include<cstdio>
#include<queue>
using namespace std;
typedef long long LL;
const int N = 5e5 + 5;
int n, m; LL a[N];
struct data {
int id, rk; LL val;
data(int id_ = 0, int rk_ = 0, LL val_ = 0) : id(id_), rk(rk_), val(val_) {}
bool operator < (const data &x) const {
return val < x.val;
}
};
priority_queue < data > q;
struct Trie {
#define M N * 40
int nex[M][2], siz[M], cnt;
Trie () { cnt = 0; }
void insert(LL x) {
int p = 0;
for(int i = 31; ~i; i--) {
int ch = (x >> i) & 1; siz[p]++;
if(!nex[p][ch]) nex[p][ch] = ++cnt;
p = nex[p][ch];
}
siz[p]++;
}
LL query(LL x, int rk) {
int p = 0; LL ans = 0;
for(int i = 31; ~i; i--) {
int ch = (x >> i) & 1;
if(!nex[p][ch ^ 1]) p = nex[p][ch];
else if(rk <= siz[nex[p][ch ^ 1]]) p = nex[p][ch ^ 1], ans |= 1LL << i;
else rk -= siz[nex[p][ch ^ 1]], p = nex[p][ch];
}
return ans;
}
}tr;
int main() {
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i++) scanf("%lld", &a[i]), a[i] = a[i] ^ a[i - 1];
for(int i = 0; i <= n; i++) tr.insert(a[i]);
for(int i = 0; i <= n; i++) q.push(data(i, 1, tr.query(a[i], 1)));
m <<= 1; LL res = 0;
for(int i = 1; i <= m; i++) {
data x = q.top(); res += x.val; q.pop();
if(x.rk < n) q.push(data(x.id, x.rk + 1, tr.query(a[x.id], x.rk + 1)));
}
printf("%lld\n", res >> 1);
return 0;
}
原文地址:https://www.cnblogs.com/sjzyh/p/15072915.html
- Entity Framework Core 2.0 入门
- 用VSCode开发一个asp.net core2.0+angular5项目(5): Angular5+asp.net core 2.0 web api文件上传
- 用VSCode开发一个asp.net core 2.0+angular 5项目(4): Angular5全局错误处理
- 用VSCode开发一个基于asp.net core 2.0/sql server linux(docker)/ng5/bs4的项目(3)
- 用VSCode开发一个基于asp.net core 2.0/sql server linux(docker)/ng5/bs4的项目(2)
- 用VSCode开发一个基于asp.net core 2.0/sql server linux(docker)/ng5/bs4的项目(1)
- element-ui el-input只显示下划线
- 怎样去阅读源码,这篇文章值的你一读
- HTML5 Blob与ArrayBuffer、TypeArray和字符串String之间转换
- Mybatis 3 配置 Log4j
- 基于Three.js的360度全景--photo-sphere-viewer--简介
- MyBatis3-配置使用log4j输出日志
- nginx支持跨域访问
- nginx静态资源文件无法访问,403 forbidden错误
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Dubbo 是如何实现 SPI 机制?
- 签到功能,用 MySQL 还是 Redis ?
- 轻松两步,在 SpringBoot 服务上实现接口限流
- 教程 | 在华为鸿蒙OS上尝鲜,第一个“hello world”
- spring-boot-route(二十二)实现邮件发送功能
- 踩坑!JDK8中HashMap依然会死循环!
- 解决 idea 使用过程中让你觉得不爽的一些问题
- R语言SIR模型(Susceptible Infected Recovered Model)代码sir模型实例
- Java循环
- 手把手教你用Python网络爬虫获取壁纸图片
- List<E>集合接口特征、ArrayList与LinkedList使用注意及特征
- Object类与它的一些方法
- IO流简要介绍
- R语言用线性回归模型预测空气质量臭氧数据
- 缓冲流简要介绍