题目链接:https://www.luogu.org/problemnew/show/P1494

题目描述

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

具体来说,小Z把这N只袜子从1到N编号,然后从编号L到R(L 尽管小Z并不在意两只袜子是不是完整的一双,甚至不在意两只袜子是否一左一右,他却很在意袜子的颜色,毕竟穿两只不同色的袜子会很尴尬。

你的任务便是告诉小Z,他有多大的概率抽到两只颜色相同的袜子。当然,小Z希望这个概率尽量高,所以他可能会询问多个(L,R)以方便自己选择。

然而数据中有L=R的情况,请特判这种情况,输出0/1。

输入输出格式

输入格式:

输入文件第一行包含两个正整数N和M。N为袜子的数量,M为小Z所提的询问的数量。接下来一行包含N个正整数Ci,其中Ci表示第i只袜子的颜色,相同的颜色用相同的数字表示。再接下来M行,每行两个正整数L,R表示一个询问。

输出格式:

包含M行,对于每个询问在一行中输出分数A/B表示从该询问的区间[L,R]中随机抽出两只袜子颜色相同的概率。若该概率为0则输出0/1,否则输出的A/B必须为最简分数。(详见样例)

输入输出样例

输入样例#1:

  1. 6 4
  2. 1 2 3 3 3 2
  3. 2 6
  4. 1 3
  5. 3 5
  6. 1 6
输出样例#1:

  1. 2/5
  2. 0/1
  3. 1/1
  4. 4/15

说明

30%的数据中 N,M ≤ 5000;

60%的数据中 N,M ≤ 25000;

100%的数据中 N,M ≤ 50000,1 ≤ L < R ≤ N,Ci ≤ N。

题解:

直接上线段树的话,由于不满足区间可加性:

假设现在要计算区间 $[L,R]$ 里每一种颜色的袜子的数量,此时我们已经分别维护好了左右两边区间 $[L,mid]$ 和 $[mid+1,R]$ 中每一种颜色的袜子的数量,然后开始向上维护:

就会发现,依然要把每种颜色的袜子在左右区间的数量加起来才能完成对一个父节点的维护,我们并不能在 $O(1)$ 的时间内完成对线段树单一节点的维护。

但此时,若已知一个区间 $[ L , R ]$ 的情况,我们可以在 $O(1)$ 的时间内确定的有 $[ L , R+1 ]$ 和 $[ L , R-1 ]$ 和 $[ L-1 , R ]$ 和 $[ L+1 , R ]$ 的情况,

假设我们现在已知 $[ L , R ]$ 的情况,需要计算的是 $[ L' , R' ]$ 的情况,易知所需时间复杂度为 $O( | L - L' | + | R - R' | )$,

那么怎么样能够较快地回答 $M$ 次询问呢?

考虑将整个长度为 $N$ 的分成 $\frac{N}{S}$ 块,每一块长度为 $S$,所有的询问先按左端点所属分块的编号进行升序排序,对于分块编号相同的,则按右端点的大小升序排序,

那么,经过排序之后按照新的顺序遍历所有询问,每次回答当前的询问,都要以上一次询问为基础,分别考虑从上一次询问到当前询问的转移中左右两个端点的变动:

对于左端点:

  上一次询问和当前询问同属一个分块时,注意左端点不是有序的,那么最多从块的一端移到另一端 $O(S)$;

  即使跨块,考虑询问的左端点是随机生成的,当 $M$ 和 $N$ 同数量级时,一般来说每个分块下面都应当存在大约 $\frac{MS}{N}$ 个询问,那么前后两次询问的转移基本就是两个相邻块间的转移,因此移动距离也是 $O(S)$;

  总共有 $M$ 个询问,总的时间复杂度是 $O(MS)$。

对于右端点:

  上一次询问和当前询问同属一个分块时,同个分块内的右端点是有序的,那么易知遍历一个分块中所有询问,右端点最多就是从 $1$ 一直移动到 $N$,一整个分块内右端点移动 $O(N)$ 次;

  而遇到上一次询问和当前询问是跨块的情形,最差的情况不过就是右端点从 $N$ 回到 $1$,也是 $O(N)$ 次;

  共 $O(\frac{N}{S})$ 个分块,所有前后两次询问的变动属于分块内变动的,合起来使得右端点共移动 $O(\frac{N^2}{S})$ 次;

  最多 $O(\frac{N}{S})$ 次跨块变动,所有前后两次询问的变动为跨快变动的,合起来使得右端点共移动 $O(\frac{N^2}{S})$ 次;

  两者加起来,时间复杂度依然 $O(\frac{N^2}{S})$。

综上,莫队的时间复杂度是 $O(MS + \frac{N^2}{S})$,取 $S = \frac{N}{\sqrt M}$,可使得时间复杂度最小为 $O(N \sqrt M)$。

那么假设某个区间 $[L,R]$ 有 $X(X \ge 2)$ 只不同袜子,那么任取两只袜子的情况数是 $C_X^2$,

假设区间内的袜子有 $1 \sim K$ 共 $K$ 种颜色,假设第 $k$ 个颜色的袜子数为 $num[k]$,那么取到同种颜色的两只袜子的可能数是 $C_{num\left[ 1 \right]}^2 + C_{num\left[ 2 \right]}^2 + \cdots + C_{num\left[ K \right]}^2$ ,

根据组合数公式可知 $C_n^2 = \frac{{n\left( {n - 1} \right)}}{2}$ ,

所以取到两只同色袜子的概率为

由于 $X = R - L + 1$ ,我们实际要查询的就是 $Q\left( {L,R} \right) = \sum\limits_{k = 1}^K {num\left[ k \right]^2 }$ ,

那么,

若区间转移时增加一只颜色为 $c$ 的袜子:

$Q\left( {L,R + 1} \right) = Q\left( {L - 1,R} \right) = Q\left( {L,R} \right) - num\left[ c \right]^2 + \left( {num\left[ c \right] + 1} \right)^2 = Q\left( {L,R} \right) + 2 \times num\left[ c \right] + 1$

若区间转移时减少一只颜色为 $c$ 的袜子:

$Q\left( {L,R - 1} \right) = Q\left( {L{\rm{ + }}1,R} \right) = Q\left( {L,R} \right) - num\left[ c \right]^2 + \left( {num\left[ c \right] - 1} \right)^2 = Q\left( {L,R} \right) - 2 \times num\left[ c \right] + 1$

AC代码:

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. typedef long long ll;
  4.  
  5. const int maxn=+;
  6. const int maxm=+;
  7.  
  8. struct Query
  9. {
  10. int block; //表示左端点所在块
  11. int id; //表示询问的原始顺序
  12. int l,r;
  13. Query(){}
  14. Query(int _blk,int _id,int _l,int _r){block=_blk,id=_id,l=_l,r=_r;}
  15. bool operator <(const Query &oth)const
  16. {
  17. return (block==oth.block)?(r<oth.r):(block<oth.block);
  18. }
  19. };
  20. vector<Query> Q;
  21.  
  22. int n,m;
  23. int c[maxn],num[maxn];
  24. ll up[maxn],down[maxn];
  25.  
  26. inline ll gcd(ll a,ll b){return b==?a:gcd(b,a%b);}
  27.  
  28. int main()
  29. {
  30. while(cin>>n>>m)
  31. {
  32. int len=n/sqrt(m);
  33. for(int i=;i<=n;i++) scanf("%d",&c[i]);
  34. Q.clear();
  35. for(int i=,l,r;i<=m;i++)
  36. {
  37. scanf("%d%d",&l,&r);
  38. Q.push_back(Query(l/len,i,l,r));
  39. }
  40. sort(Q.begin(),Q.end());
  41.  
  42. memset(num,,sizeof(num));
  43. int pl=,pr=;
  44. ll ans=;
  45. for(int i=;i<Q.size();i++)
  46. {
  47. const Query& q=Q[i];
  48. if(q.l==q.r)
  49. {
  50. up[q.id]=;
  51. down[q.id]=;
  52. continue;
  53. }
  54. down[q.id]=(ll)(q.r-q.l+)*(q.r-q.l);
  55. if(pr<q.r)
  56. {
  57. for(int j=pr+;j<=q.r;j++)
  58. {
  59. ans=ans+*num[c[j]]+;
  60. num[c[j]]++;
  61. }
  62. }
  63. if(pr>q.r)
  64. {
  65. for(int j=pr;j>q.r;j--)
  66. {
  67. ans=ans-*num[c[j]]+;
  68. num[c[j]]--;
  69. }
  70. }
  71. if(pl>q.l)
  72. {
  73. for(int j=pl-;j>=q.l;j--)
  74. {
  75. ans=ans+*num[c[j]]+;
  76. num[c[j]]++;
  77. }
  78. }
  79. if(pl<q.l)
  80. {
  81. for(int j=pl;j<q.l;j++)
  82. {
  83. ans=ans-*num[c[j]]+;
  84. num[c[j]]--;
  85. }
  86. }
  87. up[q.id]=ans-(q.r-q.l+);
  88.  
  89. pl=q.l;
  90. pr=q.r;
  91. }
  92.  
  93. for(int i=;i<=m;i++)
  94. {
  95. ll g=gcd(up[i],down[i]);
  96. printf("%lld/%lld\n",up[i]/g,down[i]/g);
  97. }
  98. }
  99. }

Luogu 1494 - 小Z的袜子 - [莫队算法模板题][分块]的更多相关文章

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

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

  2. bzoj 2038 小Z的袜子 莫队算法

    题意 给你一个长度序列,有多组询问,每次询问(l,r)任选两个数相同的概率.n <= 50000,数小于等于n. 莫队算法裸题. 莫队算法:将序列分为根号n段,将询问排序,以L所在的块为第一关键 ...

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

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

  4. [日常摸鱼]bzoj2038[2009国家集训队]小Z的袜子-莫队算法

    今天来学了下莫队-这题应该就是这个算法的出处了 一篇别人的blog:https://www.cnblogs.com/Paul-Guderian/p/6933799.html 题意:一个序列,$m$次询 ...

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

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

  6. 小Z的袜子 & 莫队

    莫队学习 & 小Z的袜子 引入 莫队 由莫涛巨佬提出,是一种离线算法 运用广泛 可以解决广大的离线区间询问题 莫队的历史 早在mt巨佬提出莫队之前 类似莫队的算法和莫队的思想已在Codefor ...

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

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

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

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

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

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

随机推荐

  1. Hadoop2.2.0分布式安装配置详解[2/3]

    前言 本文主要通过对hadoop2.2.0集群配置的过程加以梳理,所有的步骤都是通过自己实际测试.文档的结构也是根据自己的实际情况而定,同时也会加入自己在实际过程遇到的问题.搭建环境过程不重要,重要点 ...

  2. 基于spring-mybatis-data-common基架快速搭建web应用

    spring-mybatis-data-common做了哪些操作 1.日志依据层级归类输出,支持扩展 2.spring-mybatis持久层基础接口集成,支持扩展 3.常用业务接口定义,支持扩展. 只 ...

  3. Android webview clearHistory 不符合逾期的解决办法

    目前在业务开发中有这么一个需求,切换不同的 Fragment, 切换回 WebView 的Fragment时候,要求是打开的初始页面,然后我在 onHiddenChanged() 方法中加载默认地址, ...

  4. Source Insight 有用设置配置

    source insight代码对齐Tab键终极版 以前也写过一个source insight代码对齐,由于自己理解不够深刻,只能解决部分问题,不能根治在source insight中对齐的代码在XX ...

  5. win10安装windows live writer 错误:OnCatalogResult:0x80190194

    到官网下载了一个在线安装程序,可是一运行就提示无法安装,显式错误"OnCatalogResult:0x80190194",如下图所示 找到windows live安装程序的安装日志 ...

  6. IDEA的maven项目中 静态文件编译的问题

    IDEA的maven项目中,默认源代码目录下的xml等资源文件并不会在编译的时候一块打包进classes文件夹,而是直接舍弃掉. 如果使用的是Eclipse,Eclipse的src目录下的xml等资源 ...

  7. Java知多少(99)Graphics2D类的绘图方法

    Java语言在Graphics类提供绘制各种基本的几何图形的基础上,扩展Graphics类提供一个Graphics2D类,它拥用更强大的二维图形处理能力,提供.坐标转换.颜色管理以及文字布局等更精确的 ...

  8. 响应式编程笔记三:一个简单的HTTP服务器

    # 响应式编程笔记三:一个简单的HTTP服务器 本文我们将继续前面的学习,但将更多的注意力放在用例和编写实际能用的代码上面,而非基本的APIs学习. 我们会看到Reactive是一个有用的抽象 - 对 ...

  9. Linux下MySQL5.7.18二进制包安装(无默认配置文件my_default.cnf)

    最新在学习MySQL,纯新手,对Linux了解的也不多,因为是下载的最新版的MySQL(MySQL5.7.18)二进制包,CentOS7.2下测试安装,方便以后折腾.大概步骤如下,安装删除反复折腾了几 ...

  10. Kubernetes集群部署之三ETCD集群部署

    kuberntes 系统使用 etcd 存储所有数据,本文档介绍部署一个三节点高可用 etcd 集群的步骤,这三个节点复用 kubernetes 集群机器k8s-master.k8s-node-1.k ...