\(\\\)

Description


给出一个数列,多次询问,每次给出一个区间 \([l_i,r_i]\) ,问在区间中随意选两个位置不同的数,是同一个数的概率有多大。

  • \(n,m\le 5\times 10^4\)

\(\\\)

Solution


莫队模板。

才发现自己还没有正经学过莫队

设 \(cnt[i]\) 表示 \(i\) 在 \([l,r]\) 中出现的个数,\(S\) 为这个区间的数集,一个区间的答案可以表示成:

\[\frac{\sum_{x\in S}C_{cnt[x]}^2}{C_{r-l+1}^2}
\]

分母好说,考虑如何求分子,不妨展开一下。

\[\sum_{x\in S}C_{cnt[x]}^2=\sum_{x\in S}\frac{cnt[x]\times(cnt[x]-1)}{2}=\frac 12\times\bigg( \sum_{x\in S}cnt[x]^2-\sum_{x\in S}cnt[x]\bigg)
\]

于是有一个机智的做法:我们设 \(ans\) 表示括号里面的东西。

每次区间移动时,假如 \(cnt[x]\to cnt[x]'\) ,那么对 \(ans\) 的更新有:

\[ans=ans-cnt[x]^2+cnt[x]+cnt[x]'^2-cnt[x]'
\]

就可以 \(O(1)\) 移动回答区间的左端点或右端点了。

关于询问的排序:左端点在同一个块内的按照右端点排序,不在同一个块内的按照左端点所在块排序。

这样每个块右端点至多移动 \(O(N)\),左端点至多移动 \(O(q\sqrt N)\) ,其中 \(q\) 是左端点在这个块内的询问个数。

总复杂度 \(O(N\sqrt N)\)

\(\\\)

Code


#include<cmath>
#include<cstdio>
#include<cctype>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define N 50010
#define R register
#define gc getchar
using namespace std;
typedef long long ll; inline ll rd(){
ll x=0; char c=gc();
while(!isdigit(c)) c=gc();
while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=gc();}
return x;
} ll ans,n,m,s[N],cnt[N],bl[N]; struct Q{ll l,r,id,ans1,ans2;}q[N]; inline bool cmp(Q x,Q y){
return bl[x.l]==bl[y.l]?x.r<y.r:bl[x.l]<bl[y.l];
} inline bool cmp1(Q x,Q y){return x.id<y.id;} inline ll C(ll x){return (x*(x-1)>>1);} ll gcd(ll x,ll y){return y?gcd(y,x%y):x;} inline void move(ll &llst,ll &rlst,ll lnew,ll rnew){
while(llst<lnew){
int x=cnt[s[llst]];
ans=ans-x*x+(x-1)*(x-1)+1;
--cnt[s[llst]]; ++llst;
}
while(llst>lnew){
--llst;
int x=cnt[s[llst]];
ans=ans-x*x+(x+1)*(x+1)-1;
++cnt[s[llst]];
}
while(rlst<rnew){
++rlst;
int x=cnt[s[rlst]];
ans=ans-x*x+(x+1)*(x+1)-1;
++cnt[s[rlst]];
}
while(rlst>rnew){
int x=cnt[s[rlst]];
ans=ans-x*x+(x-1)*(x-1)+1;
--cnt[s[rlst]]; --rlst;
}
} int main(){
ll n=rd(),m=rd();
ll t=sqrt(n);
for(R ll i=1,cntt=1;i<=n;++i){
if(i%t==0) ++cntt;
bl[i]=cntt;
}
for(R ll i=1;i<=n;++i) s[i]=rd();
for(R ll i=1;i<=m;++i){q[i].l=rd();q[i].r=rd();q[i].id=i;}
sort(q+1,q+1+m,cmp);
ll lnow=1,rnow=1;
++cnt[s[1]];
for(R ll i=1,g;i<=m;++i){
if(q[i].l==q[i].r){
q[i].ans1=0;
q[i].ans2=1;
continue;
}
move(lnow,rnow,q[i].l,q[i].r);
g=gcd(ans/2,C(q[i].r-q[i].l+1));
q[i].ans1=ans/g/2;
q[i].ans2=C(q[i].r-q[i].l+1)/g;
}
sort(q+1,q+1+m,cmp1);
for(R int i=1;i<=m;++i) printf("%lld/%lld\n",q[i].ans1,q[i].ans2);
return 0;
}

[ BZOJ 2038 ] Hose的更多相关文章

  1. 【莫队】bzoj 3781,bzoj 2038,bzoj 3289

    好像又有一个星期没更博客了.. 最近疯狂考试...唯一有点收获的就是学会了莫队这种神奇的算法.. 听起来很难..其实是一个很简单的东西.. 就是在区间处理问题时对于一个待求区间[L',R']通过之前求 ...

  2. [BZOJ 2038]小Z的袜子

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

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

    二次联通门 : BZOJ 2038: [2009国家集训队]小Z的袜子 /* BZOJ 2038: [2009国家集训队]小Z的袜子 莫队经典题 但是我并不认为此题适合入门.. Answer = ∑ ...

  4. BZOJ 2038: [2009国家集训队]小Z的袜子(hose) [莫队算法]【学习笔记】

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

  5. BZOJ 2038: [2009国家集训队]小Z的袜子(hose)

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

  6. Bzoj 2038: [2009国家集训队]小Z的袜子(hose) 莫队,分块,暴力

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

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

    莫队..先按sqrt(n)分块, 然后按块的顺序对询问排序, 同块就按右端点排序. 然后就按排序后的顺序暴力求解即可. 时间复杂度O(n1.5) --------------------------- ...

  8. BZOJ 2038: [2009国家集训队]小Z的袜子(hose) 分块

    分块大法好 2038: [2009国家集训队]小Z的袜子(hose) Time Limit: 20 Sec  Memory Limit: 259 MB Submit: 2938  Solved: 13 ...

  9. BZOJ 2038: [2009国家集训队]小Z的袜子(hose)【莫队算法裸题&&学习笔记】

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

随机推荐

  1. hdu4183往返经过至多每一个点一次/最大流

    题意:从s到t,每一个点有f值,仅仅能从f值小的到大的.到T后回来.仅仅能从f值大的到 小的,求可行否. 往返,事实上就是俩条路过去(每一个点最多一次).所以想到流量为2,跑最大流.看是否满2,又要每 ...

  2. 实战c++中的string系列--指定浮点数有效数字并转为string

    上一篇博客讲了好几种方法进行number到string的转换,这里再单独说一下float或是double到string的转换. 还是处于控件显示的原因.比方说要显示文件的大小,我们从server能够获 ...

  3. solr 7.2.1 单机及伪集群启动

    1.solr的下载: 下载地址:solr官网:http://lucene.apache.org/solr进入官网点击download或者点击链接https://lucene.apache.org/so ...

  4. 主机与虚拟机互ping

    1.设置虚拟机网络连接方式(如下图): 2.设置主机和虚拟机的ip为同一个网段,如主机ip:192.168.28.1,虚拟机ip:192.168.28.128 3.如果相互还是ping不通,就检查一下 ...

  5. BZOJ2874 训练士兵 主席树

    [啊 首先 这是道权限题,然后本人显然是没有权限的  23咳3] 最近数据结构做的越来越少..然后 就跟上次一样 ,一做就是三四种不同写法. 等价的题面: 最近GY大神在sc2的天梯中被神族虐得很惨, ...

  6. UNIX 环境模拟工具Cygwin安装及使用图文教程

    对于 UNIX 本身,也有各种称呼.IBM® 大型机用户说各种带字母 "z" 的行话,比如 IBM z/OS® 和 System z9 Virtual Machine (z/VM) ...

  7. MVC接受JSON的一些注意事项

    1.MVC接受前端传的JSON数据,相应的接受参数的位置使用@RequestBody注解进行标注 2.JSON传空字符串时,后台使用Integer进行接受时,会报for String ''一堆乱七八糟 ...

  8. bzoj 4071: [Apio2015]巴邻旁之桥【splay】

    用权值线段树会容易一些并快一些,但是想复健一下splay所以打了splay 然后果然不会打了. 解题思路: 首先把家和办公室在同一侧的提出来直接加进答案里: 对于k=1,直接选所有办公室和家的中位数即 ...

  9. bzoj 4827: [Hnoi2017]礼物【FFT】

    记得FFT要开大数组!!开到快MLE的那种!!我这个就是例子TAT,5e5都RE了 在这题上花的时间太多了,还是FFT不太熟练. 首先看70分的n方做法:从0下标开始存,先n--,把a数组倍增,然后枚 ...

  10. bzoj 2618【半平面交模板】

    #include<iostream> #include<cstdio> #include<algorithm> #include<cmath> usin ...