BZOJ 2038 小Z的袜子(hose)

来源:互联网 发布:iphone语音录制软件 编辑:程序博客网 时间:2024/04/20 16:55

题意:给出N个数,M个询问区间,对于每个询问你需要给出:区间内取出两个数相同的概率。

范围:N,M 以及每个数<=5W

解法:莫队算法模板题,可以参考莫涛的题解(baidu可得)。

分析:莫队算法的实质是给询问安排一个顺序,令(L1,R1)至(L2,R2)一直到(Lm,Rm),L,R指针的拨动次数至多为 sqrt(N)*N次,然后只要处理每次指针拨动时答案发生的变化即可,在此题中,这个转移的复杂度为O(1)。

代码:

#include<stdio.h>#include<algorithm>#include<string.h>#include<stdlib.h>#include<math.h>using namespace std;#define rep(i,a,b) for(ll i=a;i<=b;i++)#define drep(i,a,b) for(ll i=a;i>=b;i--)const int NN=50050;typedef long long ll;ll n,m;ll sum,a[NN],belong[NN],ans[NN][2],t[NN];struct node{    ll l,r,idx;}q[NN];bool cmp(node x,node y){    if(belong[x.l]==belong[y.l])return x.r<y.r;    else return x.l<y.l;}void init(){    sum=0;    rep(i,1,n)t[i]=0;    rep(i,1,n)scanf("%lld",&a[i]);    rep(i,1,m){        scanf("%lld%lld",&q[i].l,&q[i].r);        q[i].idx=i;    }    ll block=sqrt(n);    rep(i,1,n)belong[i]=(i-1)/block+1;    sort(q+1,q+1+m,cmp);}void update(ll pos,ll add){    sum-=t[a[pos]]*t[a[pos]];    t[a[pos]]+=add;    sum+=t[a[pos]]*t[a[pos]];}ll gcd(ll x,ll y){return y==0?x:gcd(y,x%y);}void solve(){    ll l=1,r=0;    rep(i,1,m){        for(;r<q[i].r;r++)update(r+1,1);        for(;r>q[i].r;r--)update(r,-1);        for(;l<q[i].l;l++)update(l,-1);        for(;l>q[i].l;l--)update(l-1,1);        ll x=sum-(r-l+1);        ll y=(r-l+1)*(r-l);        if(x==0){            ans[q[i].idx][0]=0;            ans[q[i].idx][1]=1;        }        ll k=gcd(x,y);        ans[q[i].idx][0]=x/k;        ans[q[i].idx][1]=y/k;    }    rep(i,1,m){        printf("%lld/%lld\n",ans[i][0],ans[i][1]);    }}main(){    while(scanf("%lld%lld",&n,&m)!=EOF){        init();        solve();    }}



0 0
原创粉丝点击