填个坑吧,学习了莫队算法。我也忘记是看的哪位大牛的博客&代码学习的了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. Lua 的函数库 01

    这里只介绍和插件编写比较有关的几个函数. 详细的Lua手册请参照Lua Reference Manual 5.1. table函数库 一部分的table函数只对其数组部分产生影响, 而另一部分则对整个 ...

  2. a标签至于flash之上的时候,IE浏览器无法点击连接的问题

    <a style="display: block;height: 131px;position: absolute;z-index: 999;width: 222px;backgrou ...

  3. php 递归 适合刚刚接解递归的人看

    递归,就是自己调用自己,当满足某条件时层层退出(后进先出). --------------------------------------------------------------------- ...

  4. Python自然语言工具包(NLTK)入门

    在本期文章中,小生向您介绍了自然语言工具包(Natural Language Toolkit),它是一个将学术语言技术应用于文本数据集的 Python 库.称为“文本处理”的程序设计是其基本功能:更深 ...

  5. openstack命令

    整理了Openstack命令: openstack aggregate add host openstack aggregate createopenstack aggregate deleteope ...

  6. C++经典书籍推荐

    <C++程序设计语言> <C++语言设计与演化> <C++标准程序库> <EFFECTIVE C++ 中文版> <MORE EFFECTIVE C ...

  7. oracle 归档/非归档

    1.查看oralce是归档模式还是非归档模式 SQL> select name,log_mode from v$database; NAME LOG_MODE------------------ ...

  8. hdu 2822 Dogs

    题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=2822 Dogs Description Prairie dog comes again! Someda ...

  9. bootstrap插件之Carousel

    兼容:ie9以上 特点:滑动图片看起来永远只有两帧,过度完美:是html css js的完美配合:其中html的data属性起了关键性作用 前提:normalize.css  jquery.js ht ...

  10. SQL Server数据库学习笔记-设计表时应该考虑的因素

    设计数据库其实就是设计数据库中的表.到底要注意些什么才能够设计好一个数据库呢?一个宗旨,8个建议. 一个宗旨“尽量少的表,每个表中尽量少的列,合理的表结构”. 8个建议: 第一个,首先要考虑的是咱们这 ...