洛谷 P1494 [国家集训队] 小 Z 的袜子 题解
区间相同颜色个数,可以离线,我们想到用普通莫队解决。
设 \(cnt_i\) 表示颜色为 \(i\) 的袜子的数量,则取到两只同颜色的袜子的方案数为 \(\sum^n_{i=1}cnt_i \cdot (cnt_i-1)(cnt_i \ge 2)\),总方案数为 \((r-l+1) \cdot (r-l)\)。
注意 long long,笔者因为没开而挂了 3 次/kk
//P1494 [国家集训队] 小 Z 的袜子
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int MAXN=60000;
struct Query
{
ll l,r,id;
}q[MAXN];
struct Answer
{
ll x,y;
}ans[MAXN],now;
int n,m,t,num,belong[MAXN],a[MAXN];
ll cnt[MAXN];
ll math_GCD(ll x,ll y)
{
return !y?x:math_GCD(y,x%y);
}
bool mohs_cmp(Query a,Query b)
{
return (belong[a.l]^belong[b.l])?belong[a.l]<belong[b.l]:((belong[a.l]&1)?a.r<b.r:a.r>b.r);
}
inline void mohs_add(int x)
{
cnt[x]++;
if(cnt[x]>1)
{
now.x=now.x+cnt[x]*(cnt[x]-1)-(cnt[x]-1)*(cnt[x]-2);
}
return;
}
inline void mohs_del(int x)
{
cnt[x]--;
if(cnt[x]>0)
{
now.x=now.x+cnt[x]*(cnt[x]-1)-(cnt[x]+1)*cnt[x];
}
return;
}
void _div(ll x,ll y,int i)
{
ll g;
if(!x)
{
x=0;
y=1;
}
else
{
g=math_GCD(x,y);
x/=g;
y/=g;
}
ans[i].x=x;
ans[i].y=y;
return;
}
signed main()
{
/*freopen("P1494_7.in","r",stdin);
freopen("P1494_7.out","w",stdout);*/
ll l,r,ql,qr;
scanf("%d%d",&n,&m);
t=sqrt(n);
num=ceil(n*1.0/t);
for(int i=1;i<=num;i++)
{
for(int j=(i-1)*t+1;j<=i*t;j++)
{
belong[j]=i;
}
}
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
for(int i=1;i<=m;i++)
{
scanf("%lld%lld",&q[i].l,&q[i].r);
q[i].id=i;
}
sort(&q[1],&q[m+1],mohs_cmp);
for(int i=q[1].l;i<=q[1].r;i++)
{
mohs_add(a[i]);
}
now.y=(q[1].r-q[1].l+1)*(q[1].r-q[1].l);
_div(now.x,now.y,q[1].id);
l=q[1].l;
r=q[1].r;
for(int i=2;i<=m;i++)
{
ql=q[i].l;
qr=q[i].r;
while(l<ql)
{
mohs_del(a[l++]);
}
while(l>ql)
{
mohs_add(a[--l]);
}
while(r<qr)
{
mohs_add(a[++r]);
}
while(r>qr)
{
mohs_del(a[r--]);
}
now.y=(qr-ql+1)*(qr-ql);
//cout<<q[i].id<<' '<<now.x<<' '<<now.y<<endl;
_div(now.x,now.y,q[i].id);
}
for(int i=1;i<=m;i++)
{
printf("%lld/%lld\n",ans[i].x,ans[i].y);
}
return 0;
}
/*
* 洛谷
* https://www.luogu.com.cn/problem/P1494
* C++20 -O0
* 2022.10.1
*/

浙公网安备 33010602011771号