小Z的袜子「国家集训队」

题意

给定一个数列以及若干询问,每次询问给定区间任意挑选两个数相等的概率。


思路

对于每一种颜色显然贡献为\(cnt[c]*(cnt[c]-1)\),由于我们一个个加入,所以说在加上现在贡献的同时需要减去之前的计算,即

\[+cnt[c]*(cnt[c]-1)-(cnt[c]-1)*(cnt[c]-2)\]

化简得到\(+cnt[c]*2-2\)

减去同理。

注意需要特判区间长度为1的毒瘤情况。

代码

#include <bits/stdc++.h>

using namespace std;

namespace StandardIO {

    template<typename T>inline void read (T &x) {
        x=0;T f=1;char c=getchar();
        for (; c<'0'||c>'9'; c=getchar()) if (c=='-') f=-1;
        for (; c>='0'&&c<='9'; c=getchar()) x=x*10+c-'0';
        x*=f;
    }

    template<typename T>inline void write (T x) {
        if (x<0) putchar('-'),x*=-1;
        if (x>=10) write(x/10);
        putchar(x%10+'0');
    }

}

using namespace StandardIO;

namespace Project {
    #define int long long
    
    const int N=50050;
    
    int n,m,block;
    int a[N];
    struct ask {
        int l,r,id;
    } q[N];
    int res,cnt[N];
    pair<int,int> ans[N];
    
    inline int gcd (int a,int b) {
        return (b==0)?a:gcd(b,a%b);
    }
    inline bool cmp (const ask x,const ask y) {
        return (x.l/block!=y.l/block)?(x.l/block<y.l/block):(((x.l/block)&1)?(x.r<y.r):(x.r>y.r));
    }
    inline void add (int x) {
        ++cnt[a[x]];
        if (cnt[a[x]]>1) res+=2*cnt[a[x]]-2;
    }
    inline void del (int x) {
        --cnt[a[x]];
        if (cnt[a[x]]>0) res-=cnt[a[x]]*2;
    }

    inline void MAIN () {
        read(n),read(m),block=sqrt(n);
        for (register int i=1; i<=n; ++i) 
            read(a[i]);
        for (register int i=1; i<=m; ++i) {
            read(q[i].l),read(q[i].r),q[i].id=i;
        }
        sort(q+1,q+m+1,cmp);
        int l=1,r=0;
        for (register int i=1; i<=m; ++i) {
            if (q[i].l==q[i].r) {
                ans[q[i].id].first=0,ans[q[i].id].second=1;
                continue;
            }
            while (l>q[i].l) add(--l);
            while (l<q[i].l) del(l++);
            while (r<q[i].r) add(++r);
            while (r>q[i].r) del(r--);
            int len=(r-l+1)*(r-l),tmp=gcd(res,len);
            ans[q[i].id].first=res/tmp,ans[q[i].id].second=len/tmp;
        }
        for (register int i=1; i<=m; ++i) {
            write(ans[i].first),putchar('/'),write(ans[i].second),puts("");
        }
    }
    
    #undef int
}

int main () {
//  freopen(".in","r",stdin);
//  freopen(".out","w",stdout);
    Project::MAIN();
}

猜你喜欢

转载自www.cnblogs.com/ilverene/p/11746219.html
今日推荐