【luogu P5906】【模板】回滚莫队&不删除莫队

【模板】回滚莫队&不删除莫队

题目链接:luogu P5906

题目大意

给你一个序列,多次询问每次问一个区间,求里面相同的数的最远间隔距离。

思路

考虑莫队,发现加入一个点好处理,但是删去不好处理。

考虑莫队能不能不删去,那我们考虑把删去变成从头再加。
啊当然不行,那能不能选一个节点,每次改左边就从这个节点从新向左边扩展。

距离来说就是对于一个块 x,我们枚举作为左端点所在块,那我们按右端点排序,每次确定好右端点,我们就把左端点从这个块的右端开始往左移,从而来加进去。

然后在这题里面你要维护的就是最左的某个数和最右的某个数(用桶来维护)。
然后记得还原操作不要用 memset 而是按之前贡献的路取消回去。
(也可以拿一个桶记录修改了什么地方)

具体操作看代码。

代码

#include<cmath> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int N = 2e5 + 100; int n, a[N], B, m, blo[N], bl[N], br[N]; int lst[N], ans[N], Rlst[N], Llst[N]; int clr[N], b[N], bn; struct Quest { int l, r, id; }q[N]; bool cmp(Quest x, Quest y) { if (blo[x.l] != blo[y.l]) return blo[x.l] < blo[y.l]; return x.r < y.r; } int clac(int l, int r) { int re = 0; for (int i = l; i <= r; i++) if (!lst[a[i]]) lst[a[i]] = i; else re = max(re, i - lst[a[i]]); for (int i = l; i <= r; i++) lst[a[i]] = 0; return re; } int main() { scanf("%d", &n); for (int i = 1; i <= n; i++) scanf("%d", &a[i]); //离散 memcpy(b, a, sizeof(b)); sort(b + 1, b + n + 1); bn = unique(b + 1, b + n + 1) - b - 1; for (int i = 1; i <= n; i++) a[i] = lower_bound(b + 1, b + bn + 1, a[i]) - b; B = sqrt(n); for (int i = 1; i <= n; i++) { blo[i] = (i - 1) / B + 1; if (!bl[blo[i]]) bl[blo[i]] = i; br[blo[i]] = i; } scanf("%d", &m); for (int i = 1; i <= m; i++) scanf("%d %d", &q[i].l, &q[i].r), q[i].id = i; sort(q + 1, q + m + 1, cmp); int now = 1; for (int i = 1; i <= blo[n]; i++) { int mid = br[i], l = mid + 1, r = mid, val = 0; while (now <= m && blo[q[now].l] == i) { if (blo[q[now].r] == i) { ans[q[now].id] = clac(q[now].l, q[now].r); now++; continue; } while (r < q[now].r) { r++; Rlst[a[r]] = r; if (!Llst[a[r]]) Llst[a[r]] = r, clr[++clr[0]] = a[r]; else val = max(val, r - Llst[a[r]]); } int tmp = val; while (l > q[now].l) { l--; if (!Rlst[a[l]]) Rlst[a[l]] = l; else val = max(val, Rlst[a[l]] - l); } while (l < mid + 1) { if (Rlst[a[l]] == l) Rlst[a[l]] = 0; l++; } ans[q[now].id] = val; val = tmp; now++; } for (int j = 1; j <= clr[0]; j++) Llst[clr[j]] = Rlst[clr[j]] = 0; clr[0] = 0; } for (int i = 1; i <= m; i++) printf("%d\n", ans[i]); return 0; }

__EOF__

本文作者あおいSakura
本文链接https://www.cnblogs.com/Sakura-TJH/p/luogu_P5906.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   あおいSakura  阅读(37)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示