【数据结构】【基础莫队】P1494 [国家集训队]小Z的袜子
【基础莫队】P1494 [国家集训队]小Z的袜子
-
题意:
求区间
[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;
}