您的位置:首页 > 其它

BZOJ 2038 小Z的袜子(hose) [莫队算法]

2017-07-12 08:37 337 查看
题意:给你n只袜子的颜色,询问在袜子区间【L,R】中选出两只相同颜色的袜子的概率

题解:询问量比较大,明显用莫队

#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<iostream>
#define N 50005
using namespace std;
typedef long long ll;
ll a
;
ll pos
;
ll num
;
ll len;
struct node
{
ll l,r,id;
node(){}
node(ll l,ll r,ll id)
{
this->l=r;
this->r=r;
this->id=id;
}
}q
;
ll ansa
,ansb
;
bool cmp(node a,node b)
{
return pos[a.l]<pos[b.l]||pos[a.l]==pos[b.l]&&a.r<b.r;
}
ll modify(ll p,ll add)
{
ll sum=2*add*num[a[p]]+1;
num[a[p]]+=add;
return sum;
}
ll gcd(ll a,ll b)
{
if(b!=0)return gcd(b,a%b);
return a;
}
int main()
{
ll n,m;
scanf("%lld%lld",&n,&m);
for(ll i=1;i<=n;i++)
scanf("%lld",&a[i]);
len=(ll)sqrt((double)n+0.1);
for(ll i=1;i<=n;i++)
pos[i]=(i-1)/len+1;
for(ll i=0;i<m;i++)
{
scanf("%lld%lld",&q[i].l,&q[i].r);
q[i].id=i;
}
sort(q,q+m,cmp);
ll ans=0;
ll l=1,r=0;
for(ll i=0;i<m;i++)
{
if(r<q[i].r)
{
for(r=r+1;r<=q[i].r;r++)
ans+=modify(r,1);
r--;
}
if(q[i].l<l)
{
for(l=l-1;l>=q[i].l;l--)
ans+=modify(l,1);
l++;
}
if(r>q[i].r)
{
for(;r>q[i].r;r--)
ans+=modify(r,-1);
}
if(q[i].l>l)
{
for(;l<q[i].l;l++)
ans+=modify(l,-1);
}
if(q[i].l==q[i].r)
{
ansa[q[i].id]=0,ansb[q[i].id]=1;
continue;
}
ansa[q[i].id]=ans-(q[i].r-q[i].l+1);
ansb[q[i].id]=(q[i].r-q[i].l+1)*(q[i].r-q[i].l);
ll g=gcd(ansa[q[i].id],ansb[q[i].id]);
ansa[q[i].id]/=g;
ansb[q[i].id]/=g;
}
for(ll i=0;i<m;i++)
printf("%lld/%lld\n",ansa[i],ansb[i]);

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: