• [BZOJ2038]:[2009国家集训队]小Z的袜子(hose)(离线莫队)


    题目传送门


    题目描述

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


    输入格式

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


    输出格式

    包含$M$行,对于每个询问在一行中输出分数$A/B$表示从该询问的区间$[L,R]$中随机抽出两只袜子颜色相同的概率。

    若该概率为$0$则输出$0/1$,否则输出的$A/B$必须为最简分数。(详见样例)


    样例

    样例输入

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

    样例输出

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


    数据范围与提示

    样例解释:

    询问1:共$C_5^2=10$种可能,其中抽出两个$2$有$1$种可能,抽出两个$3$有$3$种可能,概率为$frac{1+3}{10}=frac{4}{10}=2/5$。
    询问2:共$C_3^2=3$种可能,无法抽到颜色相同的袜子,概率为$frac{0}{3}=0/1$。
    询问3:共$C_3^2=3$种可能,均为抽出两个$3$,概率为$frac{3}{3}=1/1$。
    注:上述$C_a^b$表示组合数,组合数$C_a^b$等价于在$a$个不同的物品中选取$b$个的选取方案数。

    数据规模与约定:

    30%的数据中,$N,Mleqslant 5,000$;
    60%的数据中,$N,Mleqslant 25,000$;
    100%的数据中,$N,Mleqslant 50,000$,$1leqslant L<Rleqslant N$,$C_ileqslant N$。


    题解

    设区间中有$k$个不同的颜色,每种颜色有$s[i]$个,答案就是:$sum limits_{i=1}{k}frac{C_{s_i}^2}{C_n^2}$。

    之后发现只要维护$s_i^2$即可,在移动左右端点时开个桶就能简单地维护出来。

    化一下上面的式子,你会发现其实答案就是:$sum limits_{i=1}{k}frac{(s_i-1) imes s_i}{(n-1) imes n}$,这样在代码实现上就简单多了。


    代码时刻

    #include<bits/stdc++.h>
    using namespace std;
    struct rec
    {
    	int l;
    	int r;
    	int id;
    	int pos;
    }q[50001];
    int n,m;
    int a[50001];
    int cnt[50001];
    long long ans;
    long long a1[50001],a2[50001];
    bool cmp(rec a,rec b){return a.pos==b.pos?a.r<b.r:a.pos<b.pos;}
    void upd(int x,int w)//计算答案
    {
    	ans-=cnt[a[x]]*cnt[a[x]];
    	cnt[a[x]]+=w;
    	ans+=cnt[a[x]]*cnt[a[x]];
    }
    int main()
    {
    	scanf("%d%d",&n,&m);
    	int t=sqrt(n);
    	for(int i=1;i<=n;i++)
    		scanf("%d",&a[i]);
    	for(int i=1;i<=m;i++)
    	{
    		scanf("%d%d",&q[i].l,&q[i].r);
    		q[i].id=i;
    		q[i].pos=(q[i].l-1)/t+1;
    	}
    	sort(q+1,q+m+1,cmp);
    	int l=1,r=0;
    	for(int i=1;i<=m;++i)
    	{
    		while(l<q[i].l)upd(l++,-1);
    		while(l>q[i].l)upd(--l,1);
    		while(r<q[i].r)upd(++r,1);
    		while(r>q[i].r)upd(r--,-1);
    		if(l==r){a1[i]=0,a2[i]=1;}
    		long long x=ans-(r-l+1);//分子
    		long long y=(long long)(q[i].r-q[i].l+1)*(q[i].r-q[i].l);//分母
    		long long g=__gcd(x,y);//约分
    		a1[q[i].id]=x/g,a2[q[i].id]=y/g;
    	}
    	for(int i=1;i<=m;i++)
    		cout<<a1[i]<<'/'<<a2[i]<<endl;
    	return 0;
    }
    

    rp++

  • 相关阅读:
    MySQL LIMIT OFFSET
    Sublime Text 3安装清爽主题(著名的Soda Theme)
    MySQL无法远程连接解决方案
    算法题:李嘉诚保险柜密码问题
    一些不错的算法学习练习站点
    [转]MySQL远程连接ERROR 2003 (HY000):Can't connect to MySQL server on'XXXXX'(111) 的问题
    使用什么工具连接MySQL Server
    CentOS 7修改MySQL 5.6字符集为UTF-8
    CentOS 7 Minimal编译安装MySQL5.6
    如何使浏览器默认下载文件而不是打开文件
  • 原文地址:https://www.cnblogs.com/wzc521/p/11240851.html
Copyright © 2020-2023  润新知