题意

题目链接

分析

  • 记操作异或和为 \(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]的更多相关文章

  1. LibreOJ #517. 「LibreOJ β Round #2」计算几何瞎暴力

    二次联通门 : LibreOJ #517. 「LibreOJ β Round #2」计算几何瞎暴力 /* LibreOJ #517. 「LibreOJ β Round #2」计算几何瞎暴力 叫做计算几 ...

  2. 「LibreOJ β Round #2」计算几何瞎暴力

    https://loj.ac/problem/517 题解 首先我们如果没有排序这个骚操作的话,可以直接记一下各个数位的前缀和,然后异或标记给全局打,查询的时候先把区间信息提取出来然后整体异或就好了. ...

  3. [LOJ#531]「LibreOJ β Round #5」游戏

    [LOJ#531]「LibreOJ β Round #5」游戏 试题描述 LCR 三分钟就解决了问题,她自信地输入了结果-- > -- 正在检查程序 -- > -- 检查通过,正在评估智商 ...

  4. [LOJ#530]「LibreOJ β Round #5」最小倍数

    [LOJ#530]「LibreOJ β Round #5」最小倍数 试题描述 第二天,LCR 终于启动了备份存储器,准备上传数据时,却没有找到熟悉的文件资源,取而代之的是而屏幕上显示的一段话: 您的文 ...

  5. [LOJ#516]「LibreOJ β Round #2」DP 一般看规律

    [LOJ#516]「LibreOJ β Round #2」DP 一般看规律 试题描述 给定一个长度为 \(n\) 的序列 \(a\),一共有 \(m\) 个操作. 每次操作的内容为:给定 \(x,y\ ...

  6. [LOJ#515]「LibreOJ β Round #2」贪心只能过样例

    [LOJ#515]「LibreOJ β Round #2」贪心只能过样例 试题描述 一共有 \(n\) 个数,第 \(i\) 个数 \(x_i\) 可以取 \([a_i , b_i]\) 中任意值. ...

  7. [LOJ#525]「LibreOJ β Round #4」多项式

    [LOJ#525]「LibreOJ β Round #4」多项式 试题描述 给定一个正整数 k,你需要寻找一个系数均为 0 到 k−1 之间的非零多项式 f(x),满足对于任意整数 x 均有 f(x) ...

  8. [LOJ#526]「LibreOJ β Round #4」子集

    [LOJ#526]「LibreOJ β Round #4」子集 试题描述 qmqmqm有一个长为 n 的数列 a1,a2,……,an,你需要选择集合{1,2,……,n}的一个子集,使得这个子集中任意两 ...

  9. [LOJ#522]「LibreOJ β Round #3」绯色 IOI(危机)

    [LOJ#522]「LibreOJ β Round #3」绯色 IOI(危机) 试题描述 IOI 的比赛开始了.Jsp 和 Rlc 坐在一个角落,这时他们听到了一个异样的声音 …… 接着他们发现自己收 ...

随机推荐

  1. Android Studio NDK JNI动态注册本地方法

    概述 可能大家觉得javah生成的函数名又臭又长,不太好看.这里可以提供另外一种方法来动态注册c++函数,让其根Java中的native方法关联起来. 实现 这里通过JNIEnv的Resisterna ...

  2. wangEditor更改默认高度

    在使用WangEditor时觉得高度太低,默认是300px;想调下高度,借鉴https://blog.csdn.net/qq_31384551/article/details/83240188, 网址 ...

  3. ZooKeeper使用命令大全

    stat path [watch]    set path data [version]    ls path [watch]    delquota [-n|-b] path    ls2 path ...

  4. 配置正确情况下,hadoop 没有namenode的一个解决方法

    将hdfs里name与data清空,和将tmp清空 然后在hadoop目录下运行 hadoop namenode -format 启动   sbin/start-all.sh

  5. mssql sqlserver 验证整型函数分享

    转自:http://www.maomao365.com/?p=6227 摘要: 下文将制作一个isnumber验证整型的函数,供在sql脚本中做数值判断,如下所示: 例: 实现原理:判断 是否包含特殊 ...

  6. Python平时代码的一些知识

      os.walk的作用: def file_name(file_dir): for root, dirs, files in os.walk(file_dir): print(root) #当前目录 ...

  7. c/c++ allocator 使用

    allocator 使用 作用:只开辟空间,不调用构造函数 操作一览表 allocator<T> a 定义一个名为a的allocator对象,它可以为类型为T的对象分配内存 a.alloc ...

  8. spyder 快捷键

    本文主要介绍了spyder的快捷键. 常用快捷键   快捷键 中文名称 Ctrl+R 替换文本 Ctrl+1 单行注释,单次注释,双次取消注释 Ctrl+4 块注释,单次注释,双次取消注释 F5 运行 ...

  9. ASP.NET -- WebForm -- .aspx与.aspx.cs文件

    ASP.NET -- WebForm --  .aspx与.aspx.cs文件 1. ASP.NET -- WebForm(C#)文件 .aspx文件:是Html页面,页面的布局,样式在该文件中设计. ...

  10. 【2018.08.19 C与C++基础】编程语言类型系统简介(草稿)

    还是先占坑,等理顺了思路再写,学过的东西总是无法系统化,感觉什么都知道一点,但一深入却是一脸懵逼. 这真的是个问题,看似很努力,却无法成为一个master. 参考链接: 1. 编程语言的类型系统为何如 ...