P1494 [国家集训队]小Z的袜子

偷偷地切莫队模板题。。。

讲道理这道题也是很普通的莫队模板题。

让你求了个概率,其实就是问你\(\sum{\frac{cnt[i] \times (cnt[i]-1)}{2}}\)。分母是人都能求吧。求出两个东西之后约分即可。

分子这个东西,其实就是一道同样的莫队题“小B的询问”中的维护方法。

每多一个数,答案就不一样。那么我们减掉当前的对答案的贡献, 更新cnt数组,再加上新的对答案的贡献,就可以维护了。

代码:

#include<cstdio>
#include<cmath>
#include<algorithm>
#define LL long long
const int maxn = 50005;
struct Query
{
    LL l, r, id;
} ques[maxn];
LL belong[maxn];
LL out1[maxn], out2[maxn];
LL cnt[maxn];
LL a[maxn];
LL n, m;
LL l = 1, r = 0, ans = 0;
bool cmp(Query a, Query b)
{
    if(belong[a.l] == belong[b.l]) return a.r < b.r;
    return belong[a.l] < belong[b.l];
}
LL read()
{
    LL ans = 0, s = 1;
    char ch = getchar();
    while(ch > '9' || ch < '0'){ if(ch == '-') s = -1; ch = getchar(); }
    while(ch >= '0' && ch <= '9') ans = (ans << 3) + (ans << 1) + ch - '0', ch = getchar();
    return s * ans;
}
void add(LL x)
{
    ans -= (cnt[x] * (cnt[x] - 1)) / 2;
    cnt[x]++;
    ans += (cnt[x] * (cnt[x] - 1)) / 2;
}
void del(LL x)
{
    ans -= (cnt[x] * (cnt[x] - 1)) / 2;
    cnt[x]--;
    ans += (cnt[x] * (cnt[x] - 1)) / 2;
}
void moqueue()
{
    LL block = sqrt(n);
    for(int i = 1; i <= n; i++) belong[i] = (i - 1) / block + 1;
    std::sort(ques + 1, ques + m + 1, cmp);
    for(int i = 1; i <= m; i++)
    {
        if(ques[i].l == ques[i].r)
        {
            out1[ques[i].id] = 0, out2[ques[i].id] = 1;
            continue;
        }
        while(l < ques[i].l) del(a[l++]);
        while(l > ques[i].l) add(a[--l]);
        while(r > ques[i].r) del(a[r--]);
        while(r < ques[i].r) add(a[++r]);
        out1[ques[i].id] = ans;
        out2[ques[i].id] = (r - l + 1) * (r - l) / 2;
    }
}
LL gcd(LL x, LL y)
{
    return y == 0 ? x : gcd(y, x % y);
}
int main()
{
    n = read(), m = read();
    for(int i = 1; i <= n; i++) a[i] = read();
    for(int i = 1; i <= m; i++) ques[i].l = read(), ques[i].r = read(), ques[i].id = i;
    moqueue();
    for(int i = 1; i <= m; i++)
    {
        LL ans1 = out1[i], ans2 = out2[i];
        LL g = gcd(ans1, ans2);
        ans1 /= g; ans2 /= g;
        printf("%lld/%lld\n", ans1, ans2);
    }
    return 0;
}
posted @ 2018-10-24 21:52  Garen-Wang  阅读(135)  评论(0编辑  收藏  举报