[BZOJ2038][2009国家集训队]小Z的袜子(hose)(莫队)

题目描述

传送门

题解

首先求概率的方法为:假设在LR这段区间里颜色为 x,y,z 的袜子分别有 a,b,c 个。
那么概率(利用排列组合推导)
p=a(a1)2+b(b1)2+c(c1)2+(RL+1)(RL)2
=a2+b2+c2+(a+b+c+)(RL+1)(RL)
a2+b2+c2+(RL+1)(RL+1)(RL)
那么我们用莫队算法+分块乱搞就能求出答案。 O(nn)
首先离线操作将区间排序,按照左端点的分块的编号,同一块内按照右端点排序。然后暴力更改区间求值即可。

代码

#include
#include
#include
#include
#include
using namespace std;
#define LL long long

const int max_n=5e4+5;
const int max_m=5e4+5;
const int max_c=5e4+5;

struct hp{
    LL l,r,block,num;
}f[max_m];
struct hq{
    LL up,down;
}ans[max_m];
LL a[max_n],c[max_c];
LL n,nn,m,L,R,up,down,GCD,upans,downans;

inline int cmp(hp a,hp b){
    return a.blockif (!b) return a;
    else return gcd(b,a%b);
}

int main(){
    scanf("%lld%lld",&n,&m);
    nn=sqrt(n);
    for (int i=1;i<=n;++i)
      scanf("%lld",&a[i]);
    for (int i=1;i<=m;++i){
        scanf("%lld%lld",&f[i].l,&f[i].r);
        f[i].num=i; 
    }
    for (int i=1;i<=m;++i){
        if (f[i].l%nn==0)
          f[i].block=f[i].l/nn;
        else f[i].block=f[i].l/nn+1;
    }
    sort(f+1,f+m+1,cmp);
    L=R=1;
    c[a[1]]=1;
    up=0;
    for (int i=1;i<=m;++i){
        up+=R-L+1;

        if (f[i].lfor (int j=L-1;j>=f[i].l;--j){
            up-=c[a[j]]*c[a[j]];
            up+=(++c[a[j]])*c[a[j]];
          }
        if (f[i].r>R)
          for (int j=R+1;j<=f[i].r;++j){
            up-=c[a[j]]*c[a[j]];
            up+=(++c[a[j]])*c[a[j]];
          }
        if (f[i].l>L)
          for (int j=L;j*c[a[j]];
            up+=(--c[a[j]])*c[a[j]];
          }
        if (f[i].rfor (int j=R;j>f[i].r;--j){
            up-=c[a[j]]*c[a[j]];
              up+=(--c[a[j]])*c[a[j]];
          }

        L=f[i].l,R=f[i].r;
        up-=R-L+1;
        down=(R-L+1)*(R-L);
        if (!up){
            ans[f[i].num].up=0;
            ans[f[i].num].down=1;
            continue;
        }
        GCD=gcd(up,down);
        upans=up/GCD;
        downans=down/GCD;
        ans[f[i].num].up=upans;
        ans[f[i].num].down=downans;
    }
    for (int i=1;i<=m;++i)
      printf("%lld/%lld\n",ans[i].up,ans[i].down);
}

你可能感兴趣的:(题解,莫队)