Title

【数据结构】【基础莫队】P1494 [国家集训队]小Z的袜子

【基础莫队】P1494 [国家集训队]小Z的袜子

image

  • 题意:

    求区间[L,R]中抽到相同颜色的袜子的概率为多少?

分析

设这段区间内各种不同颜色的袜子的数量依次为a,b,c,d,e,.....

所以答案为\(\sum_{i\in 袜子}\frac{i\times{(i-1)}}{2}/\frac{(R-L+1)\times(R-L)}{2}\)

进一步有

\(\sum_{i\in 袜子}(i^{2}-i)/(R-L+1)\times(R-L)\)

\(( (\sum_{i\in 袜子}i^{2})-(R-L+1))/(R-L+1)\times(R-L)\)

代码

#include<bits/stdc++.h>
#define ll long long
#define de(x) cout<<x<<endl;
using namespace std;
const int N = 5E4+300;
int n,m,A[N],B[N],Rank[N];
ll ans1[N],ans2[N];
struct Query{
	int ql,qr,idx;
}qry[N];
int len;
int inline get(int x)
{
	return (x-1)/len;
}
bool cmp(Query& qa,Query& qb)
{
	int bloa = get(qa.ql), blob = get(qb.ql);
	if(bloa==blob) return qa.qr<qb.qr;
	return qa.ql<qb.ql;
}
ll cnt[N],temp;
void add(int x)
{
	int val = Rank[x];
	++cnt[val];
	temp += 2*cnt[ val ]-1;
	
}
void del(int x)
{
	int val = Rank[x];
	--cnt[val];
	temp -= 2*cnt[ val ]+1;
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin>>n>>m;
	len = sqrt(n);
	for(int i=1;i<=n;i++)
	    cin>>A[i],B[i]=A[i];
	    
	sort(B+1,B+1+n);
	int tot = unique(B+1,B+n+1) - B;
	for(int i=1;i<=n;i++) Rank[i] = lower_bound(B+1,B+n+1,A[i]) - B;

	for(int i=1;i<=m;i++)
	    cin>>qry[i].ql>>qry[i].qr,qry[i].idx=i;
	sort(qry+1,qry+m+1,cmp);

	int r=0,l=1;
	for(int i=1;i<=m;i++)
	{   
		int ql = qry[i].ql,qr = qry[i].qr;
		if(ql==qr)
		{
			ans1[ qry[i].idx ] = 0,ans2[ qry[i].idx ] = 1;
			continue;
		}
		while(r<qr) add(++r);
		while(r>qr) del(r--);
		while(l<ql) del(l++);
		while(l>ql) add(--l);
		ans1[ qry[i].idx ] = temp - (qr-ql+1); ans2[ qry[i].idx ] = 1ll*(qr-ql+1)*(qr-ql);
	}
	for(int i=1;i<=m;i++)
	{
		int g = __gcd(ans1[i],ans2[i]);
		cout<<ans1[i]/g<<"/"<<ans2[i]/g<<endl;
	}
	return 0;
}
posted @ 2022-02-11 00:53  BeautifulWater  阅读(37)  评论(0编辑  收藏  举报