P1494 [National Training Team] Xiao Z's Socks Foundation Mo Team

Posted by jamz310 on Wed, 09 Oct 2019 04:58:50 +0200

P1494 Socks of Little Z [National Training Team]

Label

  • Foundation Mo team

Preface

Concise title

  • Probability of Selecting Two Equal Numbers from Query Interval [L,R]

thinking

  • Mo team is very good at playing, the difficulty is how to update the probability after the pointer moves.
  • Let cnt [] be the number of occurrences of each number in the current interval, and l, r represent the endpoint of the current interval, so the answer to this interval should be:
    \[\frac{\sum\limits_{x(cnt[x>=2])} C_{cnt[x]}^{2}}{C_{r-l+1}^{2}}\]
  • (Next omit CNT [x]>= 2) Break down the number of combinations:
    \[\frac{\sum\limits_{x}( cnt[x](cnt[x]-1)}{(r-l+1)(r-l)}\]
  • It is found that the molecule is better handled. First, the original contribution of cnt[x] is subtracted, and then the new contribution is added. Now the problem lies in the denominator treatment.
    \[(r-l+1)(r-l)\]
  • Actually, ducks are also handled very well. Think of R-L as a whole, and then it's very simple. Then we should open one more variable to maintain the value of r-l. That's all.

Matters needing attention

  • longlong

summary

  • Initially l=1, r=0, then the initial r-l should be -1

AC code

#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;

const int maxn = 5e4 + 10;

long long gcd(long long a, long long b)
{
    if (b == 0) return a;
    return gcd(b, a % b);
}

struct Query
{
    int l, r, id, k;
    bool operator <(const Query& a)const
    {
        if (k == a.k)
            return r < a.r;
        return k < a.k;
    }
};

Query query[maxn];
int n, q, a[maxn];

long long cnt[maxn];
long long mu = 0, zi = 0, r_l = -1;
void add(int x)
{
    x = a[x];
    mu += 2 * r_l + 2, r_l++;
    zi -= cnt[x] * cnt[x] - cnt[x];
    cnt[x]++;
    zi += cnt[x] * cnt[x] - cnt[x];
}
void remove(int x)
{
    x = a[x];
    mu -= 2 * r_l, r_l--;
    zi -= cnt[x] * cnt[x] - cnt[x];
    cnt[x]--;
    zi += cnt[x] * cnt[x] - cnt[x];
}

pair<long long, long long> ans0[maxn];
void solve()
{
    scanf("%d%d", &n, &q);
    int len = sqrt(n / 2 * 3);
    for (int i = 1; i <= n; i++)
        scanf("%d", &a[i]);
    for (int i = 1; i <= q; i++)
        scanf("%d%d", &query[i].l, &query[i].r), query[i].id = i, query[i].k = (query[i].l - 1) / len + 1;
    sort(query + 1, query + 1 + q);

    int l = 1, r = 0;
    for (int i = 1; i <= q; i++)
    {
        int L = query[i].l, R = query[i].r, id = query[i].id;
        while (l < L) remove(l++);
        while (l > L) add(--l);
        while (r < R) add(++r);
        while (r > R) remove(r--);

        if (zi == 0 || L == R) ans0[id].first = 0, ans0[id].second = 1;
        else
        {
            long long t = gcd(zi, mu);
            ans0[id].first = zi / t, ans0[id].second = mu / t;
        }
    }

    for (int i = 1; i <= q; i++)
        printf("%lld/%lld\n", ans0[i].first, ans0[i].second);
}

int main()
{
    freopen("Testin.txt", "r", stdin);
    solve();
    return 0;
}

Topics: Python