填个坑吧,学习了莫队算法。我也忘记是看的哪位大牛的博客&代码学习的了T_T,如果您发现了的话请私信我,我会注明学自您的代码。

另外感谢@PoPoQQQ大神

好,进入正文,莫队算法,也算是一种暴力吧,从某种意义上来说……是一种对暴力的强大优化= =

对于区间的莫队是基于【分块】的思想,这一点有些类似求离散对数的【大步小步算法】。

首先我们来考虑一个赤果果的暴力算法:对于每个询问,从L到R枚举一遍,统计每种袜子出现的次数,然后用组合数学的方法算出抽到两只相同袜子的方案数,和所有抽取袜子的总方案数。(至于求GCD然后约分什么的应该都懂的)

实际上,我们在进行暴力枚举的时候,有很多区间在不同的询问中计算了多次,而实际上这些已经进行过的计算完全是可以尽可能地进行再次利用的!两个相差不大的询问的结果相似度是很高的,我们完全可以在进行完一个[l,r]的计算后,进行少许更改,快速转移到[l',r']。

这就可以通过对询问顺序进行适当调整来实现:没错!排序!

那么问题来了:要按照什么样的顺序来排序呢?莫队发明的莫队算法提出了一种很科学的解决方案:分块。

把长度为N的序列分为sqrt(N)块,每块大小为sqrt(N),然后按 l 所在块的先后顺序排,l 在同一块内的按r的递增顺序排。(为什么这样分?根据基本不等式等等等等可以推出这样复杂度最低啊!当然如果带修改还会有别的分法)

排好序了,接下来就好办啦~先算出来这个块第一个询问的答案,然后不断执行-1+1调整区间。详细内容看代码注释吧~

 //BZOJ 2038
#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define rep(i,n) for(int i=0;i<n;++i)
#define F(i,j,n) for(int i=j;i<=n;++i)
#define D(i,j,n) for(int i=j;i>=n;--i)
using namespace std;
const int N=;
typedef long long LL; int n,sqr;
struct qes{
LL t,l,r;
bool operator < (const qes &a) const{
return (l/sqr)<(a.l/sqr) || (l/sqr)==(a.l/sqr) && r<a.r;
}//第一个条件是按 l 所在块排,第二个条件是按 r 单调增
}q[N]; LL gcd(LL a,LL b){
if (!b) return a;
else return gcd(b,a%b);
} LL Ans[N][]; int m,c[N],cnt[N]; int main(){
#ifndef ONLINE_JUDGE
freopen("file.in","r",stdin);
#endif
scanf("%d%d",&n,&m);
sqr=int(sqrt(n));
F(i,,n) scanf("%d",&c[i]);
F(i,,m){
scanf("%d%d",&q[i].l,&q[i].r);
q[i].t=i;
}
sort(q+,q+m+); LL rec;
int l,r;
F(i,,m){
if (i== || q[i].l/sqr != q[i-].l/sqr){
//如果是一个新的块就重新计算(将这个块第一个询问结果作为当前块所有询问的基底)
F(j,,n) cnt[j]=;
l=q[i].l; r=q[i].r;
F(j,l,r) ++cnt[c[j]];//本询问区间内计数统计
rec=;//rec表示选出相同袜子的方案数
F(j,,n) rec+=(LL)(cnt[j])*(LL)(cnt[j]-);
} //这三个for循环是 -1 +1 更新本节点的值
for(;r<q[i].r;++r){
//对于l在同一个块中的q,是按r单调增的顺序排序了的……
int s=c[r+];
rec-=(LL)(cnt[s])*(LL)(cnt[s]-);
++cnt[s];
rec+=(LL)(cnt[s])*(LL)(cnt[s]-);
//重新计算当前区间的答案
//比如原来是[2,3,3]现在变成了[2,3,3,3]那么就要减去颜色为3的袜子对答案的贡献
//再加上数量增加了1以后 它对答案的贡献
}
for(;l<q[i].l;++l){
//但是在同一块中,l并不一定是单调增的,所以会有向左右两个方向的调整
//这是向右
int s=c[l];
rec-=(LL)(cnt[s])*(LL)(cnt[s]-);
--cnt[s];
rec+=(LL)(cnt[s])*(LL)(cnt[s]-);
}
for(;l>q[i].l;--l){
//这是向左
int s=c[l-];
rec-=(LL)(cnt[s])*(LL)(cnt[s]-);
++cnt[s];
rec+=(LL)(cnt[s])*(LL)(cnt[s]-);
}
if (rec){
LL ret=gcd(rec,(LL)(r-l+)*(LL)(r-l));
Ans[q[i].t][]=rec/ret;
Ans[q[i].t][]=((LL)(r-l+)*(LL)(r-l))/ret;
} else Ans[q[i].t][]=,Ans[q[i].t][]=;//按询问顺序保存&输出
}
F(i,,m) printf("%lld/%lld\n",Ans[i][],Ans[i][]);
return ;
}

【BZOJ】【2038】小Z的袜子的更多相关文章

  1. bzoj 2038 小Z的袜子(hose)(莫队算法)

    2038: [2009国家集训队]小Z的袜子(hose) Time Limit: 20 Sec  Memory Limit: 259 MBSubmit: 11542  Solved: 5166[Sub ...

  2. (原创)BZOJ 2038 小Z的袜子(hose) 莫队入门题+分块

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

  3. BZOJ - 2038 小Z的袜子(普通莫队)

    题目链接:小Z的袜子 题意:$n$只袜子,$m$个询问,每次回答有多大概率在$[L,R]$区间内抽到两只颜色相同的袜子 思路:普通莫队,如果两个询问左端点在一个块内,则按询问右端点排序,否则按照所在块 ...

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

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

  5. BZOJ 2038 小Z的袜子(hose) 莫队算法模板题

    题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=2038 题目大意: 作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色的袜子中 ...

  6. BZOJ 2038 小z的袜子(莫队)

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

  7. [BZOJ 2038]小Z的袜子

    传送门:BZOJ 2038 题意很明确,是在给定的区间内任意选取两个数,求选到两个相同的数的概率. 所以我们得首先统计在给定的区间内,相同的数对有多少对,那么这里就使用到了莫队算法.如果对莫队算法还不 ...

  8. BZOJ 2038 小Z的袜子(hose)(分组)

    题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2038 题意:给出n个袜子.m个询问,每个询问一个区间[L,R],询问这个区间中任意拿出两 ...

  9. bzoj 2038 小z的袜子 莫队例题

    莫队,利用可以快速地通过一个问题的答案得到另一问题的答案这一特性,合理地组织问题的求解顺序,将已解决的问题帮助解决当前问题,来优化时间复杂度. 典型用法:处理静态(无修改)离线区间查询问题. 线段树也 ...

  10. [bzoj] 2038 小Z的袜子(hose) || 莫队

    原题 给出一个序列,求给定[l,r]内有任意取两个数,有多大概率是一样的 简单的莫队,每次+-当前区间里有的这个颜色的袜子的个数,最后除以(r-l+1)*(r-l)/2即可. 记得约分. #inclu ...

随机推荐

  1. 定时重启Apache与MySQL方法

    可以定时重启apache服务器等.让网站运行的效果更快. 采用at命令添加计划任务. 有关使用语法可以到window->“开始”->运行“cmd”->执行命令“at /”,这样界面中 ...

  2. C# 常用的dialogresult reset 以及if else 等检查获取客户操作信息的操作方法

    DialogResult reset; reset= MessageBox.Show("请检查您的输入信息是否按照规则输入的", "信息输入好像有问题哦", M ...

  3. Python学习教程(learning Python)--2.3.4Python函数返回值

    本节讨论Python函数返回值问题. Python和C语言一样,也可以在函数结束时返回一个值.但在定义自己的Python函数时,是不需要指定返回值数据类型的,这和Python不关心变量的数据类型是一致 ...

  4. .NET开源工作流RoadFlow-流程设计-流程属性设置

    打开流程设计器点击新建流程后会弹出新流程属性设置框,属性设置包括基本信息,数据连接和标识字段三项设置. 1.基本信息 流程ID:系统自动给每个流程分配的一个唯一ID. 流程名称:给您的新流程取一个名称 ...

  5. Linux ls -l内容详解

    ls -l是列出当前目录下所有文件信息 以下是实例: 具体的文字描述如下: 第1字段:  文件属性字段文件属性字段总共有10个字母组成,第一个字母表示文件类型,如果这个字母是一个减号”-”,则说明该文 ...

  6. 数据持久化-Plist文件写入

    数据持久化,常见4种:归档,plist文件,sqlite,coreData.今天复习的是plist文件读写. // // ViewController.m // Test_Plist // // Cr ...

  7. sharepoint 2010 找不到搜索不到ad里的用户

    前提条件: 1.这个用户是在ad中存在的. 2.这个用户也同步到了userprofile中. 问题现象: 在sharepoint的人员选择器中,搜索不到已经添加的用户. 可能原因: 1.有人说需要将 ...

  8. 29.DDR2问题1仿真模型文件

    在使用modelsim仿真DDR2时,一般我们会用美光网站上下载的DDR2仿真模型.仿真模型文件一般有ddr2_module.v,ddr2.v,ddr2_mcp.v,ddr2_parameters.v ...

  9. 二、secureCRT的 使用过程

    准备工作: win7与linux能互相ping通 linux安装了ssh被登陆服务 关闭window 防火墙,,控制面板 下载secureCRT 参考资料:http://zhidao.baidu.co ...

  10. “psp”软件需求规约

    1 系统概述 1.1 概述 该产品是基于软件开发的个人软件过程(personal software process)系统.基本信息有软件开发人员,项目经理,研发经理和管理层登录系统后根据各自的相应权限 ...