[LOJ#517]. 「LibreOJ β Round #2」计算几何瞎暴力[trie]
题意
分析
记操作异或和为 \(tx\) ,最后一次排序时的异或和为 \(ax\) ,每个数插入时的 \(tx\) 记为 \(b\)。
我们发现,一旦数列排序,就会变得容易操作。
对于新加入的数字用一个前缀和数组维护每一位为 1 的个数(每个数保证在 \(xor\) 当前 \(tx\) 之后能够得到真实结果)。对于进行过排序的数字用 trie 维护(每个数用 \(a_i\ xor\ b_i\) 表示)。
查找 trie 上的数字在 \(xor\ ax\) 排序后的前 \(k\) 个值中每一位有多少个1,如果 \(ax\) 对应位是 1 就先走右子树。
如果要进行新的排序,就将没插入 trie 的数字以 \(a_i\ xor\ b_i\) 插入到 trie 中即可。
时间复杂度 \(O(nlogn)\) 。
代码
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
#define go(u) for(int i = head[u], v = e[i].to; i; i=e[i].lst, v=e[i].to)
#define rep(i, a, b) for(int i = a; i <= b; ++i)
#define pb push_back
#define re(x) memset(x, 0, sizeof x)
inline int gi() {
int x = 0,f = 1;
char ch = getchar();
while(!isdigit(ch)) { if(ch == '-') f = -1; ch = getchar();}
while(isdigit(ch)) { x = (x << 3) + (x << 1) + ch - 48; ch = getchar();}
return x * f;
}
template <typename T> inline bool Max(T &a, T b){return a < b ? a = b, 1 : 0;}
template <typename T> inline bool Min(T &a, T b){return a > b ? a = b, 1 : 0;}
const int N = 2e5 + 7;
int n, tp, m;
int a[N], num[N];
int ax, totx;
int f[N][33], res[33];
namespace Trie {
const int Nd = N * 33;
int ch[Nd][2], ndc = 1, son[Nd], sum[Nd][33];
void insert(int x) {
int u = 1;
for(int i = 30; ~i; --i) {
rep(j, 0, i + 1) if(x >> j & 1) ++sum[u][j];
++son[u];
int c = x >> i & 1;
if(!ch[u][c]) ch[u][c] = ++ndc;
u = ch[u][c];
}
if(x & 1)
++sum[u][0];
++son[u];
}
void query(int u, int i, int k) {
if(!u || !k || i < 0) return;
int c = ax >> i & 1;
if(son[ch[u][c]] >= k) query(ch[u][c], i - 1, k), res[i] += c * k;
else {
rep(j, 0, i) res[j] += sum[ch[u][c]][j];
query(ch[u][c ^ 1], i - 1, k - son[ch[u][c]]);
res[i] += (c ^ 1) * (k - son[ch[u][c]]);
}
}
LL query(int l, int r) {
LL ans = 0;
re(res);
query(1, 30, r);
rep(j, 0, 30)
ans += 1ll * (totx >> j & 1 ? r - res[j] : res[j]) << j;
re(res);
query(1, 30, l - 1);
rep(j, 0, 30)
ans -= 1ll * (totx >> j & 1 ? l - 1 - res[j] : res[j]) << j;
return ans;
}
}
LL query(int l, int r) {
LL ans = 0;
memcpy(res, f[r], sizeof res);
rep(j, 0, 30)
ans += 1ll * (totx >> j & 1 ? r - res[j] : res[j]) << j;
memcpy(res, f[l - 1], sizeof res);
rep(j, 0, 30)
ans -= 1ll * (totx >> j & 1 ? l - 1 - res[j] : res[j]) << j;
return ans;
}
int main() {
n = gi();
rep(i, 1, n) {
int x = gi();
num[++tp] = x;
rep(j, 0, 30) f[tp][j] = f[tp - 1][j] + (x >> j & 1);
}
m = gi();
while(m--) {
int opt = gi();
if(opt == 1) {
int x = gi();
num[++tp] = x ^ totx;
rep(j, 0, 30) f[tp][j] = f[tp - 1][j] + ((x ^ totx) >> j & 1);
}
if(opt == 2) {
int l = gi(), r = gi(), k = Trie::son[1];
if(r <= k)
printf("%lld\n", Trie::query(l, r));
else if(l <= k)
printf("%lld\n", query(1, r - k) + Trie::query(l, k));
else
printf("%lld\n", query(l - k, r - k));
}
if(opt == 3) {
totx ^= gi();
}
if(opt == 4) {
for(; tp; --tp) Trie::insert(num[tp]);
ax = totx;
}
}
return 0;
}
[LOJ#517]. 「LibreOJ β Round #2」计算几何瞎暴力[trie]的更多相关文章
- LibreOJ #517. 「LibreOJ β Round #2」计算几何瞎暴力
二次联通门 : LibreOJ #517. 「LibreOJ β Round #2」计算几何瞎暴力 /* LibreOJ #517. 「LibreOJ β Round #2」计算几何瞎暴力 叫做计算几 ...
- 「LibreOJ β Round #2」计算几何瞎暴力
https://loj.ac/problem/517 题解 首先我们如果没有排序这个骚操作的话,可以直接记一下各个数位的前缀和,然后异或标记给全局打,查询的时候先把区间信息提取出来然后整体异或就好了. ...
- [LOJ#531]「LibreOJ β Round #5」游戏
[LOJ#531]「LibreOJ β Round #5」游戏 试题描述 LCR 三分钟就解决了问题,她自信地输入了结果-- > -- 正在检查程序 -- > -- 检查通过,正在评估智商 ...
- [LOJ#530]「LibreOJ β Round #5」最小倍数
[LOJ#530]「LibreOJ β Round #5」最小倍数 试题描述 第二天,LCR 终于启动了备份存储器,准备上传数据时,却没有找到熟悉的文件资源,取而代之的是而屏幕上显示的一段话: 您的文 ...
- [LOJ#516]「LibreOJ β Round #2」DP 一般看规律
[LOJ#516]「LibreOJ β Round #2」DP 一般看规律 试题描述 给定一个长度为 \(n\) 的序列 \(a\),一共有 \(m\) 个操作. 每次操作的内容为:给定 \(x,y\ ...
- [LOJ#515]「LibreOJ β Round #2」贪心只能过样例
[LOJ#515]「LibreOJ β Round #2」贪心只能过样例 试题描述 一共有 \(n\) 个数,第 \(i\) 个数 \(x_i\) 可以取 \([a_i , b_i]\) 中任意值. ...
- [LOJ#525]「LibreOJ β Round #4」多项式
[LOJ#525]「LibreOJ β Round #4」多项式 试题描述 给定一个正整数 k,你需要寻找一个系数均为 0 到 k−1 之间的非零多项式 f(x),满足对于任意整数 x 均有 f(x) ...
- [LOJ#526]「LibreOJ β Round #4」子集
[LOJ#526]「LibreOJ β Round #4」子集 试题描述 qmqmqm有一个长为 n 的数列 a1,a2,……,an,你需要选择集合{1,2,……,n}的一个子集,使得这个子集中任意两 ...
- [LOJ#522]「LibreOJ β Round #3」绯色 IOI(危机)
[LOJ#522]「LibreOJ β Round #3」绯色 IOI(危机) 试题描述 IOI 的比赛开始了.Jsp 和 Rlc 坐在一个角落,这时他们听到了一个异样的声音 …… 接着他们发现自己收 ...
随机推荐
- Android为TV端助力 VelocityTracker 速度追踪器的使用及创建
VelocityTracker 速度追踪 第一,创建方式: VelocityTracker mVelocityTracker = new VelocityTracker .obtain() 第二, ...
- 运行 python *.py 文件出错,如:python a.py
运行 python *.py 文件出错,如:python a.py(下图) 原因:没有安装web.py 解决:下载并安装 网址:http://webpy.org/install#install (h ...
- mysql数据的基本操作
本文内容: 插入数据: 查询数据 修改数据 删除数据 首发日期:2018-04-11 插入数据: 给所有字段插入数据: 插入单条记录:insert into 表名 values(值列表); 插入多条记 ...
- 开发新手最容易犯的50个 Ruby on Rails 错误(1)
[编者按]本文最早发布与 JETRuby 博客,主要介绍了开发新手最容易犯的 Ruby 错误.文章系国内 ITOM 管理平台 OneAPM 编译呈现. 一年前,我们创立了以 "Rubyboo ...
- HandyEditor 富文本编辑器整合到python flask项目中
1.下载HandyEditor,地址http://he.catfish-cms.com/ 2.解压后的文件名HandyEditor-master改为HandyEditor,文件夹里的文件如下 3.将H ...
- Spark之UDF
package big.data.analyse.udfudaf import org.apache.spark.sql.types.{IntegerType, StringType, StructF ...
- 前后端分离djangorestframework——解析渲染组件
解析器 解析器的作用就是服务端接收客户端传过来的数据,把数据解析成自己想要的数据类型的过程,本质就是对请求体中的数据进行解析 Accept是告诉对方我能解析什么样的数据,通常也可以表示我想要什么样的数 ...
- python连接sqlserver数据库
1.准备工作 python3.6连接sqlserver数据库需要引入pymssql模块 pymssql官方:https://pypi.org/project/pymssql/ 没有安装的话需要: pi ...
- Java集合:List、Set和Map的区别,ArrayList和LinkedList有何区别..........
一.数组和集合的区别: 数组是大小固定的,并且同一个数组只能存放类型一样的数据(基本类型/引用类型): 集合可以存储和操作数目不固定的一组数据. 所有的JAVA集合都位于 java.util包中! J ...
- SMB协议利用之ms17-010-永恒之蓝漏洞抓包分析SMB协议
SMB协议利用之ms17-010-永恒之蓝漏洞抓包分析SMB协议 实验环境: Kali msf以及wireshark Win7开启网络共享(SMB协议) 实验步骤: 1.查看本机数据库是否开启,发现数 ...