莫队2 这次需要带修改了
莫队2 这次需要带修改了
实现修改
莫队是不支持修改的, 但是有后人加以改进, 就有了代修版本.
我们现在有一个东西叫时间轴 (类似函数式线段树的每个根都是关于某次之前的根修改或查询的), 每次询问都记录一下当前的时间轴, 每次修改都在时间轴上新建一个版本.
typedef struct _qryy { int l, r; int t, i; } qryy;
这次要可以 \(O(1)\) 给 \(([l, r], t)\) 扩展到 \(([l \pm 1, r], t)\), \(([l, r \pm 1], t)\) 和 \(([l, r], t \pm 1)\).
现在的排序第一关键字是 \(l\) 所在的块, 第二关键字是 \(r\), 第三关键字是 \(t\).
然后在记录修改的位置和值.
typedef struct _updd { int x, k; } updd;
这次举例单点修区间和
1 x k
\(a_{x} := a_{x} + k\)
2 x y
求 \(\displaystyle \sum_{i \in [x, y]} a_{i}\)
树状数组1.
显然这是树状数组/线段树板子, 但是我们还是在讨论莫队.
由于莫队本身复杂度玄学, Defad只得到了 70 分, 当然也可能是Defad在分块时分的不够好或各种玄学优化不会, 得分比Defad高可以在评论区发一下您怎么优化的.
int cmp(const void *a, const void *b) { qryy *x = (qryy*)(a), *y = (qryy*)(b); if (pos[x->l] ^ pos[y->l]) { return x->l - y->l; } else if (pos[x->r] ^ pos[y->r]) { return pos[x->r] - pos[y->r]; } else { return x->t - y->t; } } void get_ans() { int l = 1, r = 0, t = 0; qsort(q + 1, cntq, sizeof(q[0]), cmp); f1 (i, 1, cntq, 1) { while (l < q[i].l) { s -= a[l] + upd[l]; l++; } while (q[i].l < l) { l--; s += a[l] + upd[l]; } while (r < q[i].r) { r++; s += a[r] + upd[r]; } while (q[i].r < r) { s -= a[r] + upd[r]; r--; } while (t < q[i].t) { t++; if (q[i].l <= c[t].x && c[t].x <= q[i].r) { s += c[t].k; // 更新 sum } upd[c[t].x] += c[t].k; // 版本前进 } while (q[i].t < t) { if (q[i].l <= c[t].x && c[t].x <= q[i].r) { s -= c[t].k; // 更新 sum } upd[c[t].x] -= c[t].k; // 版本回退 t--; } ans[q[i].i] = s; } }
例题
例题也差不多, 但是单点赋值和单点加不同, 单点赋值可以给点值和修改值交换, 下次版本回退可以在换回来.
本题似乎块长开到 \(N^{\cfrac{2}{3}}\) 并且在排序时看 \(l\) 所在块和 \(r\) 所在块和 \(t\) 才可通过.
int cmp(const void *a, const void *b) { qryy *x = (qryy*)(a), *y = (qryy*)(b); if (pos[x->l] ^ pos[y->l]) { return x->l - y->l; //} else if (x->r ^ y->r) { // 用这个相比下方的会TLE // return x->r - y->r; } else if (pos[x->r] ^ pos[y->r]) { return pos[x->r] - pos[y->r]; } else { return x->t - y->t; } } void get_ans() { int l = 1, r = 0, t = 0; qsort(q + 1, cntq, sizeof(q[0]), cmp); f1 (i, 1, cntq, 1) { while (l < q[i].l) { s -= (--clr[a[l++]] == 0); } while (q[i].l < l) { s += (++clr[a[--l]] == 1); } while (r < q[i].r) { s += (++clr[a[++r]] == 1); } while (q[i].r < r) { s -= (--clr[a[r--]] == 0); } while (t < q[i].t) { t++; if (q[i].l <= c[t].x && c[t].x <= q[i].r) { s -= (--clr[a[c[t].x]] == 0); s += (++clr[c[t].k] == 1); } c[t].k ^= a[c[t].x]; a[c[t].x] ^= c[t].k; c[t].k ^= a[c[t].x]; } while (q[i].t < t) { if (q[i].l <= c[t].x && c[t].x <= q[i].r) { s -= (--clr[a[c[t].x]] == 0); s += (++clr[c[t].k] == 1); } c[t].k ^= a[c[t].x]; a[c[t].x] ^= c[t].k; c[t].k ^= a[c[t].x]; t--; } ans[q[i].i] = s; } }
原文来自CnBlogs, 作者: 指针神教教主Defad.
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10亿数据,如何做迁移?
· 推荐几款开源且免费的 .NET MAUI 组件库
· 清华大学推出第四讲使用 DeepSeek + DeepResearch 让科研像聊天一样简单!
· c# 半导体/led行业 晶圆片WaferMap实现 map图实现入门篇
· 易语言 —— 开山篇