[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 Studio多渠道打包(二)
虽然多渠道打包的方式有很多种,那么今天我要说的通过工具的形式进行多渠道打包 首先,打开Android studio,找到顶部Build,点开 选择红色部分,里面的编辑框可以帮助我们更快的熟悉Gradl ...
- (办公)eclipse连接github cannot open git-upload-pack(git-receive-pack)
原文地址:https://blog.csdn.net/royal__moon/article/details/79427431 打开eclipse安装目录下的eclipse.ini添加一句:-Dhtt ...
- 2步安装1个hive docker运行环境[centos7]
1 构建基础容器 基于centos环境docker环境快速搭建,执行步骤 docker build -t cenosbase7 . 执行此步骤就可以构建1个基础的centos基础运行环境 相关的文件如 ...
- ORACLE中Scalar subquery Caching的hash table大小测试浅析
前阵子总结了这篇"ORACLE当中自定义函数性优化浅析"博客,里面介绍了标量子查询缓存(scalar subquery caching),如果使用标量子查询缓存,ORACLE会 ...
- asp.net core 发布到 docker 容器时文件体积过大及服务端口的配置疑问
在 asp.net core 发布时,本人先后产生了3个疑问. 1.发布的程序为什么不能在docker容器中运行 当时在window开发环境中发布后,dotnet xxx.dll可以正常运行:但放入d ...
- java----java垃圾回收算法
1.引用计数法(Reference Counting Collector) 1.1算法分析 引用计数是垃圾收集器中的早期策略.在这种方法中,堆中每个对象实例都有一个引用计数.当一个对象被创建时,且将该 ...
- 4.5Python数据处理篇之Matplotlib系列(五)---plt.pie()饼状图
目录 目录 前言 (一)简单的饼状图 (二)添加阴影和突出部分 (三)显示图例和数据标签: 目录 前言 饼状图需要导入的是: plt.pie(x, labels= ) (一)简单的饼状图 (1)说明: ...
- SAP 维护视图创建与修改
维护视图创建与修改 维护视图创建 T-CODE:SE54 维护ABAP数据字典 维护已生产的对象 注意:当维护视图修改后,需要删除已生成的对象,重新创建已生成的对象,否则无法显示,这个小窍门我花了半天 ...
- 13.scrapy框架的日志等级和请求传参
今日概要 日志等级 请求传参 如何提高scrapy的爬取效率 今日详情 一.Scrapy的日志等级 - 在使用scrapy crawl spiderFileName运行程序时,在终端里打印输出的就是s ...
- linux历史命令查找快捷方式
一.回到上次操作的目录# cd -进入上次访问目录 二.历史命令搜索操作快捷键:[Ctrl + r], [Ctrl + p], [Ctrl + n] 在终端中按捉 [Ctrl] 键的同时 [r] ...