luogu P1494 [国家集训队]小Z的袜子 ( 普 通 )

题目:    链接:https://www.luogu.org/problemnew/show/P1494

                题意:一些袜子排成一排,每个袜子有固定的颜色。
                          每次询问在[l,r]的袜子中等概率选两只,求有多大的概率抽到两只一样颜色的。

 

思路: 其实 就是 求     莫队维护 一波 cnt[ i ] * cnt[ i ]    就是模板嘛

 

 

#include<bits/stdc++.h>
#define LL long long
using namespace std;
int c[500005],pos[500005];
LL num[500005],up[500005],dw[500005],ans,u,v,w;
struct note {
    int l,r,id;
}a[500005];
bool cmp(note uu,note vv) {
    if(pos[uu.l]==pos[vv.l]) return uu.r<vv.r;
    return pos[uu.l]<pos[vv.l];
}
void updat(int x,int d) {
    ans-=num[c[x]]*num[c[x]];
    num[c[x]]+=d;
    ans+=num[c[x]]*num[c[x]];
}
int main() {
    int n,q;
    scanf("%d %d",&n,&q);
    int m=(int)sqrt(n);
    for(int i=1;i<=n;i++) {
        scanf("%d",&c[i]);
        pos[i]=(i-1)/m;
    }
    for(int i=1;i<=q;i++) {
        scanf("%d %d",&a[i].l,&a[i].r); a[i].id=i;
    }
    sort(a+1,a+1+q,cmp);
    int l=1;int r=0; ans=0; memset(num,0,sizeof(num));
    for(int i=1;i<=q;i++) {
        int in=a[i].id;
        if(a[i].l==a[i].r) {
            up[in]=0,dw[in]=1; continue;
        }

        if(r<a[i].r) {
            for(int j=r+1;j<=a[i].r;j++) updat(j,1);
        }
        else {
            for(int j=r;j>a[i].r;j--) updat(j,-1);
        }
        r=a[i].r;

        if(l<a[i].l) {
            for(int j=l;j<a[i].l;j++) updat(j,-1);
        }
        else {
            for(int j=l-1;j>=a[i].l;j--) updat(j,1);
        }
        l=a[i].l;

        u=ans-a[i].r+a[i].l-1;
        v=(LL)(a[i].r-a[i].l+1)*(a[i].r-a[i].l);
        w=__gcd(u,v); u/=w; v/=w; up[in]=u; dw[in]=v;
    }
    for(int i=1;i<=q;i++) printf("%lld/%lld\n",up[i],dw[i]);
    return 0;
}
View Code

 

 

 

posted on 2019-05-20 20:00  Willems  阅读(221)  评论(0编辑  收藏  举报

导航