莫队算法(基础莫队)小结(也做markdown测试)
莫队
基础莫队
本质是通过排序优化了普通尺取法的时间复杂度。
考虑如果某一列询问的右端点是递增的,那么我们更新答案的时候,右指针只会从左往右移动,那么i指针的移动次数是
当然,我们不可能让左右端点都单调来做到总体
考虑对左端点进行分块。
莫队排序:
左端点按照分块的编号来排,如果分块编号不同的话编号较小的靠前,如果相同的话右端点小的在前。可以证明这样排完序的话时间复杂度可以做到
这样我们把区间分成了
右指针:在每一块内部,右端点递增,所以右端点走的总数不会超过
左指针:先考虑每一次询问:
-
左指针在块内部移动,块的长度是
,因此最多只会移动 次。 -
左指针在相邻两块之间移动,最坏是从第一个块的左端点移动到第二个块的右端点,因此最坏移动
次。
因为有q次询问,所以1是
因为一共有
所以总时间复杂度为
// 代码为统计一段区间上是否有不相同的数,没有输出yes
int n, q;
int a[N];
vector<array<int, 3>> v;
int cnt[210];
int ans[N];
int len;
int get(int x) {
return x / len;
}
void adds(int x, int &res) {
if (!cnt[x]) res ++;
cnt[x] ++;
}
void del(int x, int &res) {
cnt[x] --;
if (!cnt[x]) res --;
}
void solve() {
cin >> n >> q;
len = max(1, (int)sqrt((double)n * n / q));
for (int i = 1; i <= n; i ++) {
cin >> a[i];
a[i] += 100;
}
for (int i = 1; i <= q; i ++) {
int l, r;
cin >> l >> r;
v.push_back({i, l, r});
}
auto cmp = [&](array<int, 3> &a, array<int, 3> &b) {
int i = get(a[1]), j = get(b[1]);
if (i != j) return i < j;
return a[2] < b[2];
};
sort(v.begin(), v.end(), cmp);
// i是右指针,j是左指针
for (int k = 0, i = 0, j = 1, res = 0; k < q; k ++) {
int id = v[k][0], l = v[k][1], r = v[k][2];
while (i < r) adds(a[++ i], res);
while (i > r) del(a[i --], res);
while (j < l) del(a[j ++], res);
while (j > l) adds(a[-- j], res);
ans[id] = res;
}
for (int i = 1; i <= q; i ++)
if (ans[i] == 1) cout << "YES\n";
else cout << "NO\n";
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效