【BZOJ】【2038】小Z的袜子
填个坑吧,学习了莫队算法。我也忘记是看的哪位大牛的博客&代码学习的了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的袜子的更多相关文章
- bzoj 2038 小Z的袜子(hose)(莫队算法)
2038: [2009国家集训队]小Z的袜子(hose) Time Limit: 20 Sec Memory Limit: 259 MBSubmit: 11542 Solved: 5166[Sub ...
- (原创)BZOJ 2038 小Z的袜子(hose) 莫队入门题+分块
I - 小Z的袜子(hose) 作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色的袜子中找出一双来穿.终于有一天,小Z再也无法忍受这恼人的找袜子过程,于是他决定听天由命…… 具体来说,小Z ...
- BZOJ - 2038 小Z的袜子(普通莫队)
题目链接:小Z的袜子 题意:$n$只袜子,$m$个询问,每次回答有多大概率在$[L,R]$区间内抽到两只颜色相同的袜子 思路:普通莫队,如果两个询问左端点在一个块内,则按询问右端点排序,否则按照所在块 ...
- BZOJ 2038 小z的袜子 & 莫队算法(不就是个暴力么..)
题意: 给一段序列,询问一个区间,求出区间中.....woc! 贴原题! 作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色的袜子中找出一双来穿.终于有一天,小Z再也无法忍受这恼人的找袜子过 ...
- BZOJ 2038 小Z的袜子(hose) 莫队算法模板题
题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=2038 题目大意: 作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色的袜子中 ...
- BZOJ 2038 小z的袜子(莫队)
Description 作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色的袜子中找出一双来穿.终于有一天,小Z再也无法忍受这恼人的找袜子过程,于是他决定听天由命……具体来说,小Z把这N只袜 ...
- [BZOJ 2038]小Z的袜子
传送门:BZOJ 2038 题意很明确,是在给定的区间内任意选取两个数,求选到两个相同的数的概率. 所以我们得首先统计在给定的区间内,相同的数对有多少对,那么这里就使用到了莫队算法.如果对莫队算法还不 ...
- BZOJ 2038 小Z的袜子(hose)(分组)
题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2038 题意:给出n个袜子.m个询问,每个询问一个区间[L,R],询问这个区间中任意拿出两 ...
- bzoj 2038 小z的袜子 莫队例题
莫队,利用可以快速地通过一个问题的答案得到另一问题的答案这一特性,合理地组织问题的求解顺序,将已解决的问题帮助解决当前问题,来优化时间复杂度. 典型用法:处理静态(无修改)离线区间查询问题. 线段树也 ...
- [bzoj] 2038 小Z的袜子(hose) || 莫队
原题 给出一个序列,求给定[l,r]内有任意取两个数,有多大概率是一样的 简单的莫队,每次+-当前区间里有的这个颜色的袜子的个数,最后除以(r-l+1)*(r-l)/2即可. 记得约分. #inclu ...
随机推荐
- C#访问配置文件
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.R ...
- 获取php的配置
ini_get — 获取一个配置选项的值 返回值 成功是返回配置选项值的字符串,null 的值则返回空字符串.如果配置选项不存在,将会返回 FALSE. <?php /* 我们的 php.ini ...
- PHP上传图片如何防止图片木马?
segmentfault回答: http://segmentfault.com/q/1010000000507750 一. 其实识别图片木马是很困难的,可以在一张正常的图片里加入一句话木马. 但是只要 ...
- 清理sql2000查询分析器登录名记录
注册表 HKEY_CURRENT_USER/Software/Microsoft/Microsoft SQL Server/80/Tools/Client/PrefServers
- 09-排序2 Insert or Merge
要点就是把排序每一步,判断一下是否和第二组数据相同,若相同则输出排序方法和下一次序列. According to Wikipedia: Insertion sort iterates, consumi ...
- 在EF的code frist下写稳健的权限管理系统:开篇(一)
环境:EF6.0.0.0+Autofac3.5.0.0+MVC4.0+pure6.0+Jquery IDE:vs2012,数据库:vs2008r2 搭建环境如下: 我给它取名字为cactus:仙人球, ...
- 金融系列14《QPBOC交易流程》
中国银行金融IC卡qPBOC交易时间(不含终端处理时间)要求:IC卡私钥长度1024位,交易时间 <= 500ms, 1152 <=600 ATR=3B8D800100814D220886 ...
- hdu 2612 Find a way
题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=2612 Find a way Description Pass a year learning in H ...
- 在JAVA中使用JSONObject生成json
JSON是一种轻量级的数据交换格式,在现在的web开发中,是非常常见的.在没有方便的工具之前,我们或许会使用拼字符串的形式来生成json数组,今天我们使用一个json-lib.jar包来为我们实现生成 ...
- Android之通过向WebService服务器发送XML数据获取相关服务
原理图如下: 即客户端向WebService服务器通过HTTP协议发送XML数据(内部包含调用的一些方法和相关参数数据),然后WebService服务器给客户端返回一定的XML格式的数据 ...