【ybt金牌导航6-4-2】【luogu P1903】数颜色 / 维护队列(带修莫队)

数颜色 / 维护队列

题目链接:ybt金牌导航6-4-2 / luogu P1903

题目大意

要你维护一个序列,可能会改变一个位置的数,还有询问一个区间内有多少种数。

思路

这道题有多种做法,然后我们考虑用带修莫队来做。

莫队是两个指针第一个按块搞,第二个就按个搞。
那我们带修的话我们就可以加上一个时间指针。

那也是一个道理,我们就也是分成块,然后第一个排序按左边的块排,第二个排序按右边的块排,接着就按着时间排。
然后就每次三个指针移动一下就可以了。

然后至于时间指针的移动,把位置 xa 换成 b,就相当于把 a 的贡献消除,加上 b 的贡献。

然后就差不多了,我们最优会选取 n23 的长度,这样复杂度是 n53 的。、
(搞这个长度直接用 pow 函数)

代码

#include<cmath> #include<cstdio> #include<algorithm> using namespace std; struct node { int t, x, y, num, ans; }a[140001]; int n, m, x, y, block[140001], t, col[140001]; int fr[140001], to[140001], lst[140001], sz; int q, tim, pl[140001], num[1000001], ans; bool in[140001]; char op; bool cmp(node x, node y) {//莫队的排序 if (block[x.x] != block[y.x]) return block[x.x] < block[y.x]; if (block[x.y] != block[y.y]) return block[x.y] < block[y.y]; return x.t < y.t; } void clac(int p) {//更新当前位置的值 if (in[p]) { num[col[p]]--; if (!num[col[p]]) ans--; } else { num[col[p]]++; if (num[col[p]] == 1) ans++; } in[p] ^= 1; } void change(int p, int t) {//换数 if (in[p]) { clac(p); col[p] = t; clac(p); } else col[p] = t; } bool cmp1(node x, node y) { return x.num < y.num; } int main() { scanf("%d %d", &n, &m); for (int i = 1; i <= n; i++) { scanf("%d", &lst[i]); col[i] = lst[i]; } sz = pow(n, 2.0 / 3); for (int i = 1; i <= n; i++) block[i] = (i - 1) / sz + 1; for (int i = 1; i <= m; i++) { op = getchar(); while (op != 'Q' && op != 'R') op = getchar(); if (op == 'Q') { scanf("%d %d", &x, &y); a[++q] = (node){tim, x, y, i, 0}; } else { scanf("%d %d", &x, &y); pl[++tim] = x; fr[tim] = lst[x]; to[tim] = y; lst[x] = y; } } sort(a + 1, a + q + 1, cmp); t = 0; x = 1; y = 0; for (int i = 1; i <= q; i++) { while (t < a[i].t) t++, change(pl[t], to[t]);//三个指针分别移动 while (t > a[i].t) change(pl[t], fr[t]), t--; while (x < a[i].x) clac(x), x++; while (x > a[i].x) x--, clac(x); while (y < a[i].y) y++, clac(y); while (y > a[i].y) clac(y), y--; a[i].ans = ans; } sort(a + 1, a + q + 1, cmp1); for (int i = 1; i <= q; i++) printf("%d\n", a[i].ans); return 0; }

__EOF__

本文作者あおいSakura
本文链接https://www.cnblogs.com/Sakura-TJH/p/YBT_JPDH_6-4-2.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   あおいSakura  阅读(30)  评论(0编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示