莫队学习 & 小Z的袜子

引入

莫队 由莫涛巨佬提出,是一种离线算法 运用广泛

可以解决广大的离线区间询问

莫队的历史

早在mt巨佬提出莫队之前 类似莫队的算法和莫队的思想已在Codeforces

的高手圈中小范围的流传 但mt是首位对莫队进行具体归纳总结的人

经过OIer和ACMer的改造 延伸出了许多扩展莫队 如 回滚莫队

可是俺只会普通莫队 这个坑还是以后再填吧(逃)

经典

学习

蒟蒻的我:莫队长啥样

见到mt本人就知道了

区间\([l,r]\)可以在\(O(1)\)的时间里求出相邻区间的贡献

即\([l,r + 1]\),\([l + 1,r]\),\([l - 1,r]\),\([l,r - 1]\)

那么你就可以在\(O(n \sqrt n)\)的时间里解决问题

思路

我们维护两个指针\(l和r\)在数组上跳来跳去

但若只是如此 那么莫队是无法焕发容光的

你会发现 若按读入的顺序跳来跳去 那么就会非常的Crazy

而且复杂度最高就爆掉了 达到了惊人de\(O(n^2)\)

对于莫队的题 出题人不可能让你过的 (除非数据过水

那么我们需要一个精美绝伦的\(std::sort\)让它跳得近一些

这样就可以有效地减少重复跳跃的路径

于是就变成了离线(没听说过有在线的莫队

莫队就大概是这样了吧

例题 & 实现

小Z的袜子

莫队的板子 竟然是当年的国家集训队

可见莫队的用处还是挺大的 况且NOI大纲上莫队好像是提高组的(没看过awa

对于区间\([l,r]\)内

每种颜色的袜子的贡献为\(sum[col[x]] * (sum[col[x]] - 1)\)

其中sum[i]表示颜色为i的袜子的数量 (当前区间\([l,r]\))

那么我们就有了如下更新

void revise(int x, int v) {ans -= sqr(sum[col[x]]), sum[col[x]] += v, ans += sqr(sum[col[x]]);}

对于之前的莫队形式 我们用\([l,r]\)做如下的更新

while(l < Katze[i].l) revise(l, -1), ++l;
while(l > Katze[i].l) revise(l - 1, 1), --l;
while(r < Katze[i].r) revise(r + 1, 1), ++r;
while(r > Katze[i].r) revise(r, -1), --r;

这时候我们算一下复杂度并且构造一下那个美妙绝伦的\(std::sort\)

我们将询问分块 设块的大小为\(size\)

分类讨论一下

  • l和下一次询问的l不在同一块内 需要至多\(2 \times size\)次移动 共有\(m\)次询问 时间复杂度为\(O(m \times size)\)

  • l和下一次询问的l在同一块内 最好的情况(可控)就是$O(\frac{n ^ 2}{size}) $具体如下

    当l所在块相同时才会有序 此时我们在l所在块相同的时候按排序那么我们就可以把sort写成这样

struct Feder_der_Katze{
int l, r, id;
int ans1, ans2;
friend bool operator < (const Feder_der_Katze a, const Feder_der_Katze b) {
if (bel[a.l] == bel[b.l]) return a.r < b.r;
else return a.l < b.l;
}
}Katze[N]; bool compare(Feder_der_Katze a, Feder_der_Katze b) {
return a.id < b.id;
}

那么我们跑一个块r最多跳\(O(n)\)次 总复杂度就是\(O(\frac{n ^ 2}{size})\)

综上所述 复杂度应该是\(O(n\sqrt n + \frac{n^2}{size})\)

根据不等式的知识来讲 大约在\(size = sqrt(n)\)也是一般情况下最优

总的时间复杂度\(大常数C * O(n\sqrt n) = O(跑得过)\)

温馨提示

本题中注意事项:

  • 询问的\(l = r\)需要特判

  • 写sort的时候是\(l所属的块相等时判r 不一定是l相等\)

    别问怎么知道的 不会Wrong Answer 但会Time Limit Exceeded$

Code

#include <bits/stdc++.h>

using namespace std;

int read(int x = 0, bool f = false, char ch = getchar()) {
for (; !isdigit(ch); ch = getchar()) f |= (ch == '-');
for (; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + (ch ^ 48);
return f ? ~x + 1 : x;
} const int N = 5e4 + 5; int n, m, siz, ans;
int col[N], bel[N], sum[N]; struct Feder_der_Katze{
int l, r, id;
int ans1, ans2;
friend bool operator < (const Feder_der_Katze a, const Feder_der_Katze b) {
if (bel[a.l] == bel[b.l]) return a.r < b.r;
else return a.l < b.l;
}
}Katze[N]; bool compare(Feder_der_Katze a, Feder_der_Katze b) {
return a.id < b.id;
} int gcd(int x, int y) {return !y ? x : gcd(y, x % y);} int sqr(int x) {return x * x;} void revise(int x, int v) {ans -= sqr(sum[col[x]]), sum[col[x]] += v, ans += sqr(sum[col[x]]);} signed main() {
n = read(), m = read(), siz = sqrt(n); for (int i = 1; i <= n; ++i) col[i] = read(), bel[i] = i / siz + 1; for (int i = 1; i <= m; ++i) Katze[i].l = read(), Katze[i].r = read(), Katze[i].id = i; sort(Katze + 1, Katze + 1 + m); int l = 1, r = 0;
for (int i = 1; i <= m; ++i) { while(l < Katze[i].l) revise(l, -1), ++l;
while(l > Katze[i].l) revise(l - 1, 1), --l;
while(r < Katze[i].r) revise(r + 1, 1), ++r;
while(r > Katze[i].r) revise(r, -1), --r; if (Katze[i].l == Katze[i].r) {Katze[i].ans1 = 0, Katze[i].ans2 = 1; continue;} Katze[i].ans1 = ans - (Katze[i].r - Katze[i].l + 1); Katze[i].ans2 = (Katze[i].r - Katze[i].l + 1) * (Katze[i].r - Katze[i].l); int Gcd = gcd(Katze[i].ans1, Katze[i].ans2);
Katze[i].ans1 /= Gcd, Katze[i].ans2 /= Gcd; } sort(Katze + 1, Katze + 1 + m, compare);
for (int i = 1; i <= m; ++i) printf("%d/%d\n", Katze[i].ans1, Katze[i].ans2);
return 0;
}

小Z的袜子 & 莫队的更多相关文章

  1. BZOJ 2038 [2009国家集训队]小Z的袜子 莫队

    2038: [2009国家集训队]小Z的袜子(hose) 题目连接: http://www.lydsy.com/JudgeOnline/problem.php?id=2038 Descriptionw ...

  2. 【国家集训队2010】小Z的袜子[莫队算法]

    [莫队算法][国家集训队2010]小Z的袜子 Description 作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色的袜子中找出一双来穿.终于有一天,小Z再也无法忍受这恼人的找袜子过程, ...

  3. bzoj 2308 小Z的袜子(莫队算法)

    小Z的袜子 [题目链接]小Z的袜子 [题目类型]莫队算法 &题解: 莫队算法第一题吧,建议先看这个理解算法,之后在参考这个就可以写出简洁的代码 我的比第2个少了一次sort,他的跑了1600m ...

  4. P1494 [国家集训队]小Z的袜子/莫队学习笔记(误

    P1494 [国家集训队]小Z的袜子 题目描述 作为一个生活散漫的人,小\(Z\)每天早上都要耗费很久从一堆五颜六色的袜子中找出一双来穿.终于有一天,小\(Z\)再也无法忍受这恼人的找袜子过程,于是他 ...

  5. BZOJ 2038 小z的袜子 & 莫队算法(不就是个暴力么..)

    题意: 给一段序列,询问一个区间,求出区间中.....woc! 贴原题! 作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色的袜子中找出一双来穿.终于有一天,小Z再也无法忍受这恼人的找袜子过 ...

  6. BZOJ2038 [2009国家集训队]小Z的袜子 莫队+分块

    作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色的袜子中找出一双来穿.终于有一天,小Z再也无法忍受这恼人的找袜子过程,于是他决定听天由命…… 具体来说,小Z把这N只袜子从1到N编号,然后从 ...

  7. Luogu 1494 - 小Z的袜子 - [莫队算法模板题][分块]

    题目链接:https://www.luogu.org/problemnew/show/P1494 题目描述 作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色的袜子中找出一双来穿.终于有一天 ...

  8. [国家集训队][bzoj2038] 小Z的袜子 [莫队]

    题面: 传送门 思路: 又是一道标准的莫队处理题目,但是这道题需要一点小改动:求个数变成了求概率 我们思考:每次某种颜色从i个增加到i+1个,符合要求的情况多了多少? 原来的总情况数是i*(i-1)/ ...

  9. BZOJ2038 小Z的袜子 莫队

    BZOJ2038 题意:q(5000)次询问,问在区间中随意取两个值,这两个值恰好相同的概率是多少?分数表示: 感觉自己复述的题意极度抽象,还是原题意有趣(逃: 思路:设在L到R这个区间中,x这个值得 ...

随机推荐

  1. 干了5年Android开发,突然感觉自己啥也不会,啥也不想干,还要继续吗?

    这是在某论坛看到的一名同行的吐槽: 我干了差不多5年,不过给人感觉跟只有两三年的人一样. 我觉得我不适合干程序员,主要是新东西的接受能力比其他人慢,Android技术又更新得很快,感觉总是跟不上.年纪 ...

  2. 大学同学做Java开发比我多5K,八年老Android只会crud该转Java吗?

    最近在网上看到这样一个帖子: 做了八年Android开发,感觉这块做着也挺没意思,日常工作就是做一些架构优化,质量数据监控,改一改构建脚本,最主要的是业务负责人没有一个是做客户端的,都是后端的人. 最 ...

  3. 如何让win10开机默认开启小键盘?

    如何让win10开机默认开启小键盘? windows10默认是关闭小键盘的.每次输入开机密码的时候都需要按一下小键盘开启键(numlock),才能按数字键 一.运行注册表编辑器,修改InitialKe ...

  4. ELK太重?试试KFC日志采集

    写在前面 ELK三剑客(ElasticSearch,Logstash,Kibana)基本上可以满足日志采集.信息处理.统计分析.可视化报表等一些日志分析的工作,但是对我们来说--太重了,并且技术栈不是 ...

  5. WPS:利用数据透视表将数据按指定列进行分组求和

    1.场景 如图所示:根据日期计算日期当天的总金额 2.利用数据透视表完成该操作 (1)选择金额列的某一格数据,点击上方插入--数据透视表 !!请确保表格第一行为表头 (2)在弹出的页面中直接点击&qu ...

  6. 对象池在 .NET (Core)中的应用[1]: 编程体验

    借助于有效的自动化垃圾回收机制,.NET让开发人员不在关心对象的生命周期,但实际上很多性能问题都来源于GC.并不说.NET的GC有什么问题,而是对象生命周期的跟踪和管理本身是需要成本的,不论交给应用还 ...

  7. NOIP 模拟 $38\; \rm b$

    题解 \(by\;zj\varphi\) 考虑转化问题,将计算最大公约数换为枚举最大公约数. 设 \(sum_i\) 为最大公约数为 \(i\) 的方案数,可以容斥求解,\(sum_i=f_i-\su ...

  8. .NET Core:在ASP.NET Core WebApi中使用Cookie

    一.Cookie的作用 Cookie通常用来存储有关用户信息的一条数据,可以用来标识登录用户,Cookie存储在客户端的浏览器上.在大多数浏览器中,每个Cookie都存储为一个小文件.Cookie表示 ...

  9. ant的javac任务的相关属性配置

    任务和javac命令是相似,它编译两种类型的Java文件1)没有被编译的java文件2)曾经编译过,但是class文件版本和当前对应的java文件版本不匹配的java文件. 1)javac命令支持的参 ...

  10. 解决servlet中get方式中中文乱码问题(二):装饰者模式使用

    注意,这里是针对Tomcat容器中get方式提交的servlet中获得参数,参数中有中文的时候乱码的问题: 之前我已经讲过,Tomcat8.0及以上URIEncoding都是utf-8的默认编码,不会 ...