bzoj2038小Z的袜子
Posted wzj-xhjbk
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj2038小Z的袜子相关的知识,希望对你有一定的参考价值。
莫队算法是一种针对询问进行分块的离线算法,如果已知区间 [ l , r ] 内的答案,并且可以在 (O(1)) 的时间内知道区间 [ l-1, r ],[ l , r+1 ] 的答案,即可使用莫对算法。
莫队算法维护的是当前区间的答案。
推荐一篇较好的莫队算法讲解文章( ightarrow)莫队
代码如下
#include <bits/stdc++.h>
using namespace std;
const int maxn=5e4+10;
struct node{int l,r,id,b;}q[maxn];
int n,m,size,cnt[maxn],a[maxn];
long long ans1[maxn],ans2[maxn];
bool cmp(const node& x,const node& y){return x.b==y.b?x.r<y.r:x.b<y.b;}
void read_and_parse(){
scanf("%d%d",&n,&m);
size=(int)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].b=(q[i].l-1)/size+1;
q[i].id=i;
}
sort(q+1,q+m+1,cmp);
}
long long gcd(long long x,long long y){return y?gcd(y,x%y):x;}
void solve(){
for(int i=1,lp=1,rp=0,now=0;i<=m;i++){
while(lp<q[i].l)now-=2*cnt[a[lp]]-2,--cnt[a[lp]],++lp;
while(rp>q[i].r)now-=2*cnt[a[rp]]-2,--cnt[a[rp]],--rp;
while(lp>q[i].l)--lp,now+=2*cnt[a[lp]],++cnt[a[lp]];
while(rp<q[i].r)++rp,now+=2*cnt[a[rp]],++cnt[a[rp]];
if(q[i].l^q[i].r)ans1[q[i].id]=(long long)now,ans2[q[i].id]=(long long)(q[i].r-q[i].l+1)*(q[i].r-q[i].l);
else ans1[q[i].id]=0,ans2[q[i].id]=1;
}
long long com;
for(int i=1;i<=m;i++)com=gcd(ans1[i],ans2[i]),printf("%lld/%lld
",ans1[i]/com,ans2[i]/com);
}
int main(){
read_and_parse();
solve();
return 0;
}
以上是关于bzoj2038小Z的袜子的主要内容,如果未能解决你的问题,请参考以下文章
bzoj 2038: [2009国家集训队]小Z的袜子(hose)