当前位置: 首页 > wzjs >正文

影视传媒公司网站模板安装免费下载app

影视传媒公司网站模板,安装免费下载app,网站建设如何插音乐,网站建设牜金手指花总十四莫队算法 —— 将暴力玩出花 一、 为什么需要莫队?—— 暴力法的瓶颈 我们已经学会了用分块处理一些在线的区间问题。现在,我们来看一类特殊的离线区间查询问题。 “离线”意味着我们可以把所有查询先读进来,再按我们喜欢的顺序去处理它们…

莫队算法 —— 将暴力玩出花

一、 为什么需要莫队?—— 暴力法的瓶颈

我们已经学会了用分块处理一些在线的区间问题。现在,我们来看一类特殊的离线区间查询问题。

“离线”意味着我们可以把所有查询先读进来,再按我们喜欢的顺序去处理它们。

思考一个问题:

给定一个长度为 N 的数组,M 次询问。每次询问一个区间 [l, r],问区间内有多少种数字至少出现了2次?

那我们回到最朴素的暴力。

  • 纯暴力:对于每个询问 (l, r),都for一遍,用数组统计词频。复杂度 O(M * N),无法接受。

  • 聪明的暴力:我们发现,如果已经知道了区间 [l, r] 的答案,我们似乎可以很快地算出相邻区间的答案。

    • [l, r+1] 的答案:在 [l, r] 的基础上,加入 a[r+1] 这个元素。
    • [l-1, r] 的答案:在 [l, r] 的基础上,加入 a[l-1] 这个元素。
    • [l+1, r] 的答案:在 [l, r] 的基础上,删去 a[l] 这个元素。
    • [l, r-1] 的答案:在 [l, r] 的基础上,删去 a[r] 这个元素。

这种“加入/删除一个元素”的操作,通常可以在 O(1)O(log N) 的时间内完成。这给了我们一个启发:我们可以维护一个当前区间 [L, R],通过不断移动左右端点 LR,来回答所有的查询。

新的瓶颈:如果我们按照读入的顺序处理询问,[L, R] 指针可能会在整个数组上“疯狂横跳”。比如前一个询问是 [1, 10],后一个询问是 [99990, 100000],指针移动的距离是 O(N)M 次询问,总复杂度最坏还是 O(M * N)

莫队算法的核心,就是解决这个问题:通过对询问进行巧妙的排序,最小化指针移动的总距离。

二、 莫队的核心思想 —— 分块排序

莫队算法的精髓在于它独特的排序策略,它将分块思想运用到了对“询问”的排序上。

  1. 分块:将长度为 N原数组下标分成 √N 个块,每块长度为 s = √N
  2. 排序:对所有询问 (l, r) 进行排序,规则如下:
    • 第一关键字:以询问的左端点 l 所在的块的编号为第一关键字,升序排列。
    • 第二关键字:如果 l 在同一个块内,则以询问的右端点 r 为第二关键字,升序排列。
// 排序规则
bool operator < (const Query& a, const Query& b) {if (belong[a.l] != belong[b.l]) {return belong[a.l] < belong[b.l]; // l 不在同块,按块编号排}return a.r < b.r; // l 在同块,按 r 排
}

为什么这样排序是高效的?
我们来直观地感受一下指针的移动:

  • 左指针 L

    • 当处理同一块内的所有询问时,l 的变化范围不会超过块长 √N。因此 L 每次也会在一个 √N 的范围内移动。
    • 当处理完一个块,换到下一个块时,L 才可能发生一次大的跳跃。
  • 右指针 R

    • 当处理同一块内的所有询问时,由于这些询问的 r 是升序的,所以 R 指针会单调向右移动,从左到右扫一遍。
    • 当处理完一个块,换到下一个块时,R 的位置是无序的,可能会从数组末尾跳回开头。

现在,我们来严格分析一下它的时间复杂度。

三、 复杂度分析

假设我们有 M 个询问,数组长度 N,块长 s = √N,块数n = √N。每次指针移动后更新答案的代价是 O(1)

1. 右指针 R 的移动

  • 块内移动:对于左端点在同一个块 i 的所有询问,它们的右端点 r 是递增的。所以,R 指针在处理这整个块的询问时,最多从 1 移动到 N,总移动距离是 O(N)。因为有 √N 个块,所以这部分总移动距离是 O(N * √N)
  • 块间移动:当左端点从一个块 i 换到下一个块 i+1 时,R 指针可能会从 N 跳回 1。这个过程最多发生 √N - 1 次。每次跳跃的成本是 O(N)。所以这部分总移动距离是 O(N * √N)

综合来看,右指针 R 的总移动次数是 O(N√N)

2. 左指针 L 的移动

  • 块内移动:对于任意一个询问,L 从上一个询问的左端点 l_{prev} 移动到当前询问的左端点 l_{cur}。由于 l_{prev}l_{cur} 在同一个块,它们之间的距离最多是块长 s,即 √N。所以每次移动距离是 O(√N)
  • 块间移动:当左端点从一个块 i 移动到下一个块 i+1 的时,移动距离最多是 2s,即 O(√N)

L 的每一次移动,无论是块内还是块间,距离都不会超过 O(√N)。总共有 M 个询问,所以左指针 L 的总移动次数是 O(M√N)


让我们用一个正确且有效的例子来演示这个过程

假设我们的查询是这些:(2, 5), (4, 9), (1, 18), (7, 8), (8, 12), (5, 20)

标准排序(无优化)
  1. 分块:左端点 l 属于块1(1-4)的有 (2, 5), (4, 9), (1, 18)。左端点 l 属于块2(5-8)的有 (7, 8), (8, 12), (5, 20)

  2. 排序

    • 块1内:按 r 升序 -> (2, 5), (4, 9), (1, 18)
    • 块2内:按 r 升序 -> (7, 8), (8, 12), (5, 20)
  3. 处理顺序与 R 指针移动

处理顺序查询 (l, r)R 的移动R 当前位置
1(2, 5)0 -> 55
2(4, 9)5 -> 99
3(1, 18)9 -> 1818
—换块—
4(7, 8)18 -> 88
5(8, 12)8 -> 1212
6(5, 20)12 -> 2020

总时间复杂度
将两部分加起来,总复杂度为 O(N√N + M√N)。如果 NM 同阶,就是 O(N√N)

**3. 奇偶性排序优化 **
我们发现,R 指针在换块时的大幅回跳是性能瓶颈之一。可以这样优化:/

  • 如果左端点 l 所在的块编号是奇数,则按 r 升序排。
  • 如果左端点 l 所在的块编号是偶数,则按 r 降序排。
// 奇偶性排序
bool operator < (const Query& a, const Query& b) {if (belong[a.l] != belong[b.l]) {return belong[a.l] < belong[b.l];}// 如果 belong[a.l] 是偶数,则 r 降序if (belong[a.l] % 2 == 0) {return a.r > b.r;}// 如果 belong[a.l] 是奇数,则 r 升序return a.r < b.r;
}

这样,R 指针在处理完一个块后,换到下一个块时,就无需从 N 回跳到 1,而是从当前位置继续“回头”扫描,如同耕地一样。这能省掉 R 指针换块时的 O(N) 的开销,总复杂度依然是 O(N√N + M√N),但常数会小很多。

假设我们的查询是这些:(2, 5), (4, 9), (1, 18), (7, 8), (8, 12), (5, 20)


场景二:奇偶性排序优化
  1. 排序

    • 块1(奇数块):按 r 升序 -> (2, 5), (4, 9), (1, 18)
    • 块2(偶数块):按 r 降序 -> (5, 20), (8, 12), (7, 8)
  2. 处理顺序与 R 指针移动

处理顺序查询 (l, r)R 的移动R 当前位置
1(2, 5)0 -> 55
2(4, 9)5 -> 99
3(1, 18)9 -> 1818
—换块—
4(5, 20)18 -> 2020
5(8, 12)20 -> 1212
6(7, 8)12 -> 88

在这个优化版本中,当从块1换到块2时,R 指针从 18 平滑地移动到了 20完全避免了大幅回跳。然后,在处理整个块2的过程中,R 指针再从右向左“扫描”回来。

四、 经典例题:小Z的袜子

我们来看知乎文章里的经典例题 P1494 [国家集训队]小Z的袜子。

题意:区间 [l, r] 内,随机取两只袜子,颜色相同的概率是多少?化为最简分数。

分析

  • 设区间长度为 len = r - l + 1
  • len 只袜子中取两只,总方案数是 C(len, 2) = len * (len-1) / 2
  • 设颜色 i 出现了 cnt[i] 次。取出两只颜色为 i 的方案数是 C(cnt[i], 2) = cnt[i] * (cnt[i]-1) / 2
  • 所有颜色都算上,取出两只相同颜色的总方案数是 Σ C(cnt[i], 2)
  • 概率 P = (Σ C(cnt[i], 2)) / C(len, 2) = (Σ (cnt[i]² - cnt[i])) / (len * (len-1))

核心任务
推导最优块长

我们来一步步推导。

1. 重新审视时间复杂度的构成

莫队算法的总时间开销主要来自两部分:

  1. 左指针 L 的移动开销
  2. 右指针 R 的移动开销

(排序的开销 O(M log M) 通常被指针移动的开销覆盖,我们在此暂不考虑。)

我们的目标是:选择一个合适的块长 s,使得这两部分开销之和最小。

2. 用块长 s 来表示开销

设数组长度为 N,询问数量为 M,块长为 s
那么,数组被分成的块数就是 ceil(N/s),我们近似看作 N/s

  • 左指针 L 的总移动距离:

    • 块内移动:当处理同一块内的询问时,左端点 l 的变化范围不会超过块长 s
    • 块间移动:当从一个块换到下一个块时,左指针 L 最多移动 2s 的距离。
    • 对于 M 次询问,每次询问 L 最多移动 O(s) 的距离。所以,L 的总移动次数是 O(M * s)
  • 右指针 R 的总移动距离:

    • 块内移动:对于左端点在同一个块的所有询问,由于我们对右端点 r 进行了排序(无论是单调递增还是奇偶性优化),R 指针在处理这一个块的所有询问时,最多会把 1N 的范围完整地扫一遍(或者来回扫一遍)。所以处理一个块的 R 指针移动开销是 O(N)
    • 总移动:我们总共有 N/s 个块。因此,R 指针的总移动次数就是 (块数) * (处理每块的开销),即 O((N/s) * N) = O(N^2 / s)

3. 使用均值不等式求解最优 s

现在,我们得到了总的指针移动次数(时间复杂度的主要部分):
T ( s ) = M ⋅ s + N 2 s T(s) = M \cdot s + \frac{N^2}{s} T(s)=Ms+sN2
我们的任务是找到一个 s,使得 T(s) 最小。

4. 计算最低时间复杂度

我们将最优块长 s = N / √M 代入到总复杂度 T(s) 中:
T m i n = M ⋅ ( N M ) + N 2 ( N M ) T_{min} = M \cdot \left(\frac{N}{\sqrt{M}}\right) + \frac{N^2}{\left(\frac{N}{\sqrt{M}}\right)} Tmin=M(M N)+(M N)N2

T m i n = N ⋅ M + N 2 ⋅ M N T_{min} = N \cdot \sqrt{M} + N^2 \cdot \frac{\sqrt{M}}{N} Tmin=NM +N2NM

T m i n = N M + N M = 2 N M T_{min} = N\sqrt{M} + N\sqrt{M} = 2N\sqrt{M} Tmin=NM +NM =2NM

所以,总时间复杂度为 O(N√M)

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
#define close ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
int n, m;
int B;
int tot;
const int N = 5e4 + 10;
int belong[N];
int a[N];
int ans = 0;
int cnt[N];
struct ss
{int l;int r;int index;int fz;int fm;
};
void build()
{for (int i = 1; i <= n; i++){belong[i] = (i - 1) / B + 1;}
}
void add(int x)
{if (cnt[a[x]] >= 2){ans -= (cnt[a[x]]) * (cnt[a[x]] - 1);}++cnt[a[x]];if (cnt[a[x]] >= 2){ans += (cnt[a[x]]) * (cnt[a[x]] - 1);}
}
void del(int x)
{if (cnt[a[x]] >= 2){ans -= (cnt[a[x]]) * (cnt[a[x]] - 1);}--cnt[a[x]];if (cnt[a[x]] >= 2){ans += (cnt[a[x]]) * (cnt[a[x]] - 1);}
}
void solve()
{cin >> n >> m;B = n / sqrt(m);tot = (n + B - 1) / B;for (int i = 1; i <= n; i++){cin >> a[i];}build();vector<ss> q;for (int i = 1; i <= m; i++){int l, r;cin >> l >> r;q.push_back({l, r, i, 0, 0});}sort(q.begin(), q.end(), [&](const ss &x, const ss &y){if(belong[x.l] != belong[y.l]){return belong[x.l] < belong[y.l];}if(belong[x.l] % 2 == 0){return x.r < y.r;}else{return x.r > y.r;} });int L = 1, R = 0;for (int i = 0; i < m; i++){int cntLen = q[i].r - q[i].l + 1;q[i].fm = cntLen * (cntLen - 1);while (L > q[i].l){add(--L);}while (L < q[i].l){del(L++);}while (R < q[i].r){add(++R);}while (R > q[i].r){del(R--);}if (ans == 0 or q[i].l == q[i].r){q[i].fz = 0;q[i].fm = 1;}else{int com = __gcd(ans, q[i].fm);q[i].fz = ans / com;q[i].fm = q[i].fm / com;}}sort(q.begin(), q.end(), [&](const ss &x, const ss &y){ return x.index < y.index; });for (int i = 0; i < m; i++){cout << q[i].fz << "/" << q[i].fm << endl;}
}
signed main()
{close;solve();return 0;
}

文章转载自:

http://XYJxgkeV.bpmnj.cn
http://iZ2NghkU.bpmnj.cn
http://gkC9Jbgs.bpmnj.cn
http://deGp5r80.bpmnj.cn
http://sM16rUkG.bpmnj.cn
http://ZpTWVg6y.bpmnj.cn
http://C4C5KxvI.bpmnj.cn
http://n16vYIFM.bpmnj.cn
http://4N7RwQRl.bpmnj.cn
http://iMqQNet3.bpmnj.cn
http://AD0IAVLW.bpmnj.cn
http://kr76ksfZ.bpmnj.cn
http://MzVqUUmM.bpmnj.cn
http://YkhwRBCS.bpmnj.cn
http://MMB0XvtP.bpmnj.cn
http://0WhAmWXK.bpmnj.cn
http://jPqbeWsn.bpmnj.cn
http://prGgruxz.bpmnj.cn
http://cJqw5Vcd.bpmnj.cn
http://xMO8jwDy.bpmnj.cn
http://sTE6GdBU.bpmnj.cn
http://vFhZmlyp.bpmnj.cn
http://2ImUxI2U.bpmnj.cn
http://qp3N0lYH.bpmnj.cn
http://cl5d0zKm.bpmnj.cn
http://oVWD47aR.bpmnj.cn
http://SSeTUuI1.bpmnj.cn
http://nAkwkihe.bpmnj.cn
http://BAZiWaf4.bpmnj.cn
http://PKuREZmu.bpmnj.cn
http://www.dtcms.com/wzjs/626057.html

相关文章:

  • 网站规划建设与管理维护教程温州网站设计服务商
  • 响应式网站是什么意思申请注册商标需要多少钱
  • 百度 医疗网站建设业之峰
  • 台山住房和城乡建设 网站用python做网页
  • 哈尔滨住房和城乡建设局网站首页广州比较好的网站建设
  • 大型网站团队人数企业信息查询系统官网湖北
  • 宜城营销型网站套餐logo在线制作免费生成器无水印
  • 英语网站开发wordpress 免费摄影主题
  • 兰州seo网站排名wordpress 背景颜色
  • 做网站数据库有哪些石家庄互联网公司有哪些
  • 1微信网站怎么建设wordpress 文章点赞功能
  • qq是哪年开始有的南昌网站排名优化报
  • 免费建站网站行业门户网站案例分析
  • 云建站优势做的网站每年都要收费吗
  • 网站搭建需要服务器吗开发网站手机版
  • 大连电子学校网站建设免费的云电脑
  • 牡丹江0453免费信息网站前端开发包括哪些内容
  • 免费公司介绍网站怎么做济南高新区网站建设公司
  • 手机网站前四川煤矿基本建设工程公司网站
  • 网站建设app开发 微信小程序 网站开发 自动脚本如何查询百度搜索关键词排名
  • 书城网站建设项目定义seo内部优化方式包括
  • 设计个网站需要怎么做武清网站开发tjniu
  • 重庆市建设领域农民工工资专户网站上海建设学院网站
  • 网站建设创业规划书广州网站制作公司多少钱
  • 新网站制作怎么样江苏建设通网站
  • 吉林省住房和城乡建设厅网站6机械加工制造网
  • 沧县网站建设泰安专业网站建设
  • 网站开发的阶段流程图给网站做数据分析
  • ps手机网站制作山西长治一企业
  • 杭州网站建设费用网站建设教程百度网盘