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

Description

作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色的袜子中找出一双来穿。终于有一天,小Z再也无法忍受这恼人的找袜子过程,于是他决定听天由命…… 
具体来说,小Z把这N只袜子从1到N编号,然后从编号L到R(L 尽管小Z并不在意两只袜子是不是完整的一双,甚至不在意两只袜子是否一左一右,他却很在意袜子的颜色,毕竟穿两只不同色的袜子会很尴尬。 
你的任务便是告诉小Z,他有多大的概率抽到两只颜色相同的袜子。当然,小Z希望这个概率尽量高,所以他可能会询问多个(L,R)以方便自己选择。

Input

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

Output

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

Sample Input

6 4 
1 2 3 3 3 2 
2 6 
1 3 
3 5 
1 6

Sample Output

2/5 
0/1 
1/1 
4/15

Hint

样例说明: 
询问1:共C(5,2)=10种可能,其中抽出两个2有1种可能,抽出两个3有3种可能,概率为(1+3)/10=4/10=2/5。 
询问2:共C(3,2)=3种可能,无法抽到颜色相同的袜子,概率为0/3=0/1。 
询问3:共C(3,2)=3种可能,均为抽出两个3,概率为3/3=1/1。 
注:上述C(a, b)表示组合数,组合数C(a, b)等价于在a个不同的物品中选取b个的选取方案数。 
数据范围: 
30%的数据中 N,M ≤ 5000; 
60%的数据中 N,M ≤ 25000; 
100%的数据中 N,M ≤ 50000,1 ≤ L < R ≤ N,Ci ≤ N。

题解

  第一次看到这题,第一想法是用线段树或者树状数组维护一下,但仔细一想,似乎不行,因为本题的区间不满足加和性质。于是就需要用到莫队算法。

  莫队算法可以解决已经知道区间[l,r]的答案,然后可以在O(1)(或者O(log N))的时间内求出[l,r+1],[l,r-1],[l-1,r],[l+1,r]的答案的问题。  

  现在知道,在区间[l,r]中,答案是 (X2+Y2+Z2.......−(r−l+1))/((r−l+1)(r−l))(X,Y,Z分别代表区间中不同颜色袜子的个数)。

  显然,这是满足上面的性质的。假如我们按照读入顺序依次求解的话,复杂度为O(n2),不是特别满意。

  这时我们就需要用到莫队算法,莫队算法的核心就是改变求解询问的顺序,从而减少运算的次数。那么,怎么样改变顺序来使速度最快呢?可以把每个区间都看做2维平面上的点,这些点的距离为横,纵坐标之差,然后我们可以O(N logN)求出这些平面点的曼哈顿最小生成树,但这样太复杂(而且我也不会)。

  所以我们可以用分块来处理,将N 分成N½块,然后我们维护一下左端点所在块的编号。以左端点的编号为第一关键字,右端点的编号为第二关键字排序;然后以排序后的顺序依次求解(所以是离线的),在求解的过程中维护答案的值。这样做的复杂度为 O(N∗N½)。以下是证明过程:

  • 时间复杂度就是左右端点移动的次数。
  • 对于右端点的移动:因为一共只有N½个块,每个块中右端点最多移动n次,所以复杂度为O(N×N½)。
  • 对于左端点的移动:如果在同一块中移动,那么是O(N½)的,如果跨越了块,那么最多跨越O(N),那么复杂度为O(N×N½+N)
  • 综上,时间复杂度为O(N×N½)。

Code

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
#define ll long long
#define REP(i,a,b) for(register int i=(a),_end_=(b);i<=_end_;i++)
#define DREP(i,a,b) for(register int i=(a),_end_=(b);i>=_end_;i--)
#define EREP(i,a) for(register int i=start[(a)];i;i=e[i].next)
inline int read()
{
int sum=,p=;char ch=getchar();
while(!((''<=ch && ch<='') || ch=='-'))ch=getchar();
if(ch=='-')p=-,ch=getchar();
while(''<=ch && ch<='')sum=sum*+ch-,ch=getchar();
return sum*p;
} const int maxn=5e4+; int n,m;
int w[maxn]; void init()
{
n=read();m=read();
REP(i,,n)w[i]=read();
} struct query {
int l,r,t,sx;
}; struct ans {
ll a,b;
}; query qu[maxn];
ans Ans[maxn];
int k; bool cmp(const query a,const query b)
{
if(a.t==b.t)return a.r<b.r;
return a.t<b.t;
} ll co[maxn]={};
ll A; void work(int x,int add)
{
A-=co[w[x]]*co[w[x]];
co[w[x]]+=add;
A+=co[w[x]]*co[w[x]]; } void doing()
{
k=(int)sqrt(n);
REP(i,,m)
{
qu[i].l=read();qu[i].r=read();
qu[i].t=(qu[i].l-)/k+;
qu[i].sx=i;
}
sort(qu+,qu+m+,cmp);
int l=,r=;
REP(i,,m)
{
while(l>qu[i].l)work(l-,),l--;
while(l<qu[i].l)work(l,-),l++;
while(r>qu[i].r)work(r,-),r--;
while(r<qu[i].r)work(r+,),r++;
if(qu[i].l==qu[i].r)
{
Ans[qu[i].sx]={,};continue;
}
Ans[qu[i].sx]={A-(r-l+),(ll)(r-l+)*(r-l)};
}
REP(i,,m)
{
ll d=__gcd(Ans[i].a,Ans[i].b);
if(d>)cout<<Ans[i].a/d<<"/"<<Ans[i].b/d<<endl;
else cout<<Ans[i].a<<"/"<<Ans[i].b<<endl;
}
} int main()
{
init();
doing();
return ;
}

【国家集训队2010】小Z的袜子[莫队算法]的更多相关文章

  1. 【bzoj2038】[国家集训队2010]小Z的袜子 莫队

    莫队:就是一坨软软的有弹性的东西Duang~Duang~Duang~ 为了防止以左端点为第一关键字以右端点为第二关键字使右端点弹来弹去,所以让左端点所在块为关键字得到O(n1.5)的时间效率,至于分块 ...

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

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

  3. AC日记——[国家集训队2010]小Z的袜子 cogs 1775

    [国家集训队2010]小Z的袜子 思路: 传说中的莫队算法(优雅的暴力): 莫队算法是一个离线的区间询问算法: 如果我们知道[l,r], 那么,我们就能O(1)的时间求出(l-1,r),(l+1,r) ...

  4. 洛谷 1775. [国家集训队2010]小Z的袜子

    1775. [国家集训队2010]小Z的袜子 ★★★   输入文件:hose.in   输出文件:hose.out   简单对比时间限制:1 s   内存限制:512 MB [题目描述] 作为一个生活 ...

  5. 数据结构(莫队算法):国家集训队2010 小Z的袜子

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

  6. [国家集训队2010]小Z的袜子

    ★★★   输入文件:hose.in   输出文件:hose.out   简单对比 时间限制:1 s   内存限制:512 MB [题目描述] 作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜 ...

  7. 1775. [国家集训队2010]小Z的袜子

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

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

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

  9. cogs1772 [国家集训队2010]小Z的袜子

    沉迷于文化的我N年没更blog了...(\(N \in (0,1)\)) 然后回到机房就沉迷于 \(generals.io\) 无法自拔...QAQ 然后想打一遍splay(然后是LCT),然后放弃了 ...

随机推荐

  1. 【编程技巧】一些 NSArray 的基本操作代码例子

    /*---------------------------切分数组------------------------------*/ //从字符串分割到数组- componentsSeparatedBy ...

  2. OpenCv结构和内容

    OpenCv的结构和内容 OpenCv源码组成结构其中包括cv, cvauex, cxcore, highgui, ml这5个模块 CV:图像处理和视觉算法 MLL:统计分类器 HighGui:GUI ...

  3. 无废话XML--XML解析(DOM和SAX)

    XML处理模式 处理XML有2种方式,DOM和SAX.一般的实际开发中,这2种使用的不多,直接用dom4j来解析XML就好了,包括CRUD等操作都很方便的.这里介绍的DOM和SAX是比较底层的,具体的 ...

  4. zabbix图形乱码

    毕竟是中文为主,特别是有些香项目最好以中文命名,容易区分,也方便识别 环境: centos7.3安装zabbix3.2 问题: 图文乱码问题 原理上只要找到对应的字符集,在修改配置文件 windows ...

  5. 2017-12-30-如何彻底清除现存GIT仓库的大量提交历史

    layout: post title: 2017-12-30-如何彻底清除现存GIT仓库的大量提交历史 key: 20171230 tags: GIT 版本管理 问答 modify_date: 201 ...

  6. oralce plsql案例练习

    以下plsql程序用的scott用户的dept,emp表. 案例1 --查询80,81,82,87年员工入职人数 set serveroutput on declare cursor cemp is ...

  7. Django中不返回QuerySets的API -- Django从入门到精通系列教程

    该系列教程系个人原创,并完整发布在个人官网刘江的博客和教程 所有转载本文者,需在顶部显著位置注明原作者及www.liujiangblog.com官网地址. Python及Django学习QQ群:453 ...

  8. R语言-单一变量分析

    R语言简介: R语言是一门专用于统计分析的语言,有大量的内置函数和第三方库来制作基于数据的表格 准备工作 安装R语言 https://cran.rstudio.com/bin/windows/base ...

  9. Community Stories: Cinemachine and Timeline——Community Stories: Cinemachine and Timeline

    Community Stories: Cinemachine and Timeline 社区故事:Cinemachine 和 Timeline Adam Myhill, 八月 25, 2017 原文: ...

  10. LANMP系列教程之Apache编译安装CentOS7环境

      1.准备好源码包并配置好yum源,需要的源码包包括:httpd-2.4.18.apr-1.5.2.tar.gz.apr-util-1.5.4.tar.gz 2.准备用户 groupadd -r a ...