题目传送门:LOJ #510

题意简述:

给出一个在 \(K\) 进制下的树状数组,但是它的实现有问题。

形式化地说,令 \(\mathrm{lowbit}(x)\) 为在 \(K\) 进制下的 \(x\) 的最低非零位的值,例如 \(\mathrm{lowbit} \!\left( 230_{(5)} \right)\! = 30_{(5)}\)。

add(x, v) 操作执行的是:

当 \(x \le n\) 时,执行 s[x] ^= v,并将 \(x\) 变为 \(x + \mathrm{lowbit}(x)\),并继续循环。

query(x) 操作执行的是:

令 \(ans\) 的初始值为 \(0\)。

当 \(x > 0\) 时,执行 ans ^= s[x],并将 \(x\) 变为 \(x - \mathrm{lowbit}(x)\),并继续循环。

最终返回 \(ans\)。

题解:

不同于正确写法,add 操作执行时的运算次数不是 \(\mathcal O ( K \log_K n )\) 的,而是 \(\mathcal O (n)\) 的,观察何时它的复杂度会发生变化:

当 \(K = 3, x = 1\) 时,\(x\) 的变化为(十进制下):\(1 \to 2 \to 4 \to 5 \to 7 \to 8 \to 10 \to \cdots\)。

可以发现,\(x\) 在 \(K\) 进制下的最低非零位的位置始终不变,而且最低非零位的值陷入了 \(1, 2, 1, 2, \ldots\) 的循环。

对于不同的 \(K\),我们观察特定的最低非零位的值的变化,发现有的最终变成了 \(0\),即这一位不再是非零的,而有的落入了循环中。

很显然,这其实就是在函数 \(f(x) = 2x \bmod K\) 对应的图上转移的过程,这张图是一个基环内向森林,其中有一个连通分量的根是 \(0 \to 0\) 的自环,与 \(0\) 相连的点最终都会提升最低非零位。

数论告诉我们,每棵基环内向树的深度都不会超过 \(\log_2 K\),如果所在的是根为 \(0\) 的基环内向树,最低位也只会变化 \(\log_K n\) 次,总次数为 \(\log_2 K \times \log_K n = \log_2 n\),所以这部分暴力跳即可。

当最终落到了不为 \(0\) 的环上时,参考上面的例子,会形成一条无限向后延伸的链,但是它是一个相邻位置的差有循环节的链。

如果将每条链预处理出来,就可以对每条链开一个树状数组,以维护后缀加,单点查的操作。

但是这里值域太大,无法直接预处理,所以考虑用倍增的方法直接求出该点在链上的编号,即 \(x\) 是在当前链上的第几个位置,就可以直接进行树状数组操作了(当然此时值域仍然是极大的,但是可以通过哈希的方法将改动的位置映射到小数组中)。

询问的时候同理,query 时 \(x\) 只会变化 \(\log_K n\) 次,所以可以每次直接查,首先判断 \(x\) 是否在链上,如果不是直接修改 \(ans\) 即可,否则需要在当前链对应的树状数组上进行单点查的操作(前面的修改对应的是后缀加),做个差分就可以变成单点加、前缀查了,就是经典的树状数组操作,对于大值域同理采用哈希的方法即可。

下面是代码,假设哈希的时间复杂度为 \(\mathcal O (1)\),则总时间复杂度为 \(\mathcal O (K \log n + q \log_K n \log n)\):

#include <cstdio>

const int HASH = 19260817, NUMS = 10000005;
int h[HASH], nxt[NUMS], to[NUMS], tot;
inline int Hasher(int val, int typ) {
int cyp = (val ^ val >> 1) % HASH;
for (int i = h[cyp]; i; i = nxt[i]) if (to[i] == val) return i;
return typ ? nxt[++tot] = h[cyp], to[tot] = val, h[cyp] = tot : 0;
} typedef long long LL;
const int MK = 200005; int N, K, Q, V[6], C;
inline void lowbit(int x, int &y, int &z) {
int s = 1, t = C;
while (t) { if (x % V[t] == 0) x /= V[t], s *= V[t]; --t; }
y = x % K, z = y * s;
}
int ltrs[MK][30], ntrs[MK][30];
LL lsum[MK][30], nsum[MK][30];
int arr[NUMS]; int main() {
scanf("%d%d%d", &N, &Q, &K);
for (LL x = K; x <= N; x *= x) V[++C] = x;
for (int i = 1; i < K; ++i) if ((i & -i) >= (K & -K))
ltrs[i * 2 % K][0] = lsum[i * 2 % K][0] = i,
ntrs[i][0] = i * 2 % K, nsum[i][0] = i;
for (int j = 0; j < 29; ++j)
for (int i = 1; i < K; ++i) if ((i & -i) >= (K & -K))
ltrs[i][j + 1] = ltrs[ltrs[i][j]][j],
lsum[i][j + 1] = lsum[i][j] + lsum[ltrs[i][j]][j],
ntrs[i][j + 1] = ntrs[ntrs[i][j]][j],
nsum[i][j + 1] = nsum[i][j] + nsum[ntrs[i][j]][j];
for (int i = 1; i <= Q; ++i) {
int op, x, y, z, v, d;
scanf("%d%d", &op, &x);
if (op == 1) {
scanf("%d", &v);
while (x <= N) {
lowbit(x, y, z);
if ((y & -y) >= (K & -K)) {
int id = 0, X = x, Y = y, w = z / y;
for (int j = 29; j >= 0; --j)
if (lsum[Y][j] < X / w)
id |= 1 << j,
X -= lsum[Y][j] * w,
Y = ltrs[Y][j];
++id;
for (int j = 0; x <= N; ++j) if (id >> j & 1) {
arr[Hasher(x, 1)] ^= v;
x += nsum[y][j] * w;
y = ntrs[y][j];
id += 1 << j;
}
break;
}
arr[Hasher(x, 1)] ^= v;
x += z;
}
} else {
int Ans = 0;
while (x) {
lowbit(x, y, z);
if ((y & -y) >= (K & -K)) {
int id = 0, X = x, Y = y, w = z / y;
for (int j = 29; j >= 0; --j)
if (lsum[Y][j] < X / w)
id |= 1 << j,
X -= lsum[Y][j] * w,
Y = ltrs[Y][j];
++id;
X = x, Y = y;
for (int j = 0; id; ++j, id >>= 1) if (id & 1) {
if ((d = Hasher(X, 0))) Ans ^= arr[d];
X -= lsum[Y][j] * w;
Y = ltrs[Y][j];
}
} else if ((d = Hasher(x, 0))) Ans ^= arr[d];
x -= z;
}
printf("%d\n", Ans);
}
}
return 0;
}

LOJ 510: 「LibreOJ NOI Round #1」北校门外的回忆的更多相关文章

  1. LOJ#510. 「LibreOJ NOI Round #1」北校门外的回忆(线段树)

    题面 传送门 题解 感谢\(@M\_sea\)的代码我总算看懂题解了-- 这个操作的本质就是每次把\(x\)的\(k\)进制最低位乘\(2\)并进位,根据基本同余芝士如果\(k\)是奇数那么最低位永远 ...

  2. #510. 「LibreOJ NOI Round #1」动态几何问题

    题目: 题解: 几何部分,先证明一下 \(KX = \sqrt{a},YL = \sqrt{b}\) 设左侧的圆心为 \(O\) ,连接 \(OK\) ,我们有 \(OK = r\). 然后有 \(r ...

  3. LOJ#508. 「LibreOJ NOI Round #1」失控的未来交通工具

    题意 一个带边权无向图,有两种操作:加边以及询问在\(x,x+b,...,x+(c-1)b\)这些数中,有多少个数存在至少一条与之模\(m\)同余的从\(u\)到\(v\)的路径(可以不是简单路径). ...

  4. 「LibreOJ NOI Round #2」不等关系

    「LibreOJ NOI Round #2」不等关系 解题思路 令 \(F(k)\) 为恰好有 \(k\) 个大于号不满足的答案,\(G(k)\) 表示钦点了 \(k\) 个大于号不满足,剩下随便填的 ...

  5. LibreOJ #507. 「LibreOJ NOI Round #1」接竹竿

    二次联通门 : LibreOJ #507. 「LibreOJ NOI Round #1」接竹竿 /* LibreOJ #507. 「LibreOJ NOI Round #1」接竹竿 dp 记录一下前驱 ...

  6. LOJ575. 「LibreOJ NOI Round #2」不等关系 [容斥,分治FFT]

    LOJ 思路 发现既有大于又有小于比较难办,使用容斥,把大于改成任意减去小于的. 于是最后的串就长成这样:<<?<?<??<<<?<.我们把一段连续的& ...

  7. 「LibreOJ NOI Round #1」验题

    麻烦的动态DP写了2天 简化题意:给树,求比给定独立集字典序大k的独立集是哪一个 主要思路: k排名都是类似二分的按位确定过程. 字典序比较本质是LCP下一位,故枚举LCP,看多出来了多少个独立集,然 ...

  8. #509. 「LibreOJ NOI Round #1」动态几何问题

    下面给出部分分做法和满分做法 有一些奇妙的方法可以拿到同样多的分数,本蒟蒻只能介绍几种常见的做法 如果您想拿18分左右,需要了解:质因数分解 如果您想拿30分左右,需要了解:一种较快的筛法 如果您想拿 ...

  9. #507. 「LibreOJ NOI Round #1」接竹竿 dp

    题目: 题解: 我们考虑把每对花色相同的牌看作区间. 那么如果我们设 \(f_i\) 表示决策在 \([1,i]\) 内的最优答案. 那么有 \(f_i = max\{max\{(f_{j-1}+\s ...

随机推荐

  1. Conda和Python的国内安装源

    Conda和Python的国内安装源 Windows系统: 更换python国内源的方法. 在"C:\Users[xxxx]\pip\pip.ini"文件中配置如下内容(没有则新建 ...

  2. jTopo介绍(一)

    jTopo(Javascript Topology library)是一款完全基于HTML5 Canvas的关系.拓扑图形化界面开发工具包.jTopo关注于数据的图形展示,它是面向开发人员的,需要进行 ...

  3. layui实现分页

    一 准备工作 首先必须先引入layui的完整目录,也就是你下载下来的整个layui的目录都要放在你的资源文件夹下,也就是这个文件目录 刚开始接触layui的时候,以为和jquery,vue等框架一样, ...

  4. Vue v-for操作对象与数值

    <!doctype html> <html lang="en"> <head id="head"> <meta cha ...

  5. 深入理解Linux内核 学习笔记(8)

    第八章 系统调用 API定义了一个给定的服务:系统调用是通过软中断向内核发出一个明确的请求. API可能不调用系统调用,也可能调用多个系统调用. Linux系统调用必须通过执行int 0x80,系统调 ...

  6. Mac 电脑无法登陆 账号了

    版本:10.14.2 每次输入用户名和密码都没有反应: 进入 命令行执行: defaults delete com.apple.appstore.commerce Storefront 然后重启机器, ...

  7. 【MySQL】Mariadb主从复制

    Mariadb主从复制 环境配置: Master : 172.30.200.200 Slave : 172.30.200.204 架构图,如下: Master的配置: 1.binlog配置 [root ...

  8. 我在生产项目里是如何使用Redis发布订阅的?(一)使用场景

    转载请注明出处! 导语 Redis是我们很常用的一款nosql数据库产品,我们通常会用Redis来配合关系型数据库一起使用,弥补关系型数据库的不足. 其中,Redis的发布订阅功能也是它的一大亮点.虽 ...

  9. 『CSP2019-S 第二轮退役记』

    Day0 到杭州的时候是下午,休息了一下就吃完饭了. 晚上的时候闲着没事复习了一下几个不太熟的数论板子,\(\mathrm{exgcd}\),\(\mathrm{ExCRT}\),\(\mathrm{ ...

  10. 【02】Nginx:基本配置和日志处理

    写在前面的话 Nginx 在安装完成后自动为我们生成了一个展示欢迎页的虚拟主机,除此之外,还附带了很多基础的配置,我们先来看看这些配置有什么用,顺便添加一些常用但是配置文件中并未初始化进去的配置来专门 ...