zoukankan      html  css  js  c++  java
  • 「题解」洛谷 P1494 [国家集训队]小Z的袜子

    题目

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

    思路

    (ans = sum_{i = 1}^{n} p_i)(p_i) 是拿到两根颜色为 (i) 的袜子的概率。

    (p_i = dfrac{s_i imes (s_i - 1)}{len imes (len - 1)})(s_i) 是颜色 (i) 在区间中出现的次数,(len) 是区间长度。

    用莫队维护出现次数,分子很容易算,分母是固定的,约分一下。

    Code

    #include <cmath>
    #include <cstdio>
    #include <cstring>
    #include <string>
    #include <iostream>
    #include <algorithm>
    #define M 50001
    
    typedef long long ll;
    ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
    
    ll now, fz[M], fm[M];
    int n, m, sqrn, a[M], num[M], cnt[M];
    struct query {
        int x, y, len, id;
        friend bool operator < (query q1, query q2) {
            if (num[q1.x] == num[q2.x]) return q1.y < q2.y;
            return num[q1.x] < num[q2.x];
        }
    }q[M];
    
    void add(int x) {
        int temp = cnt[x]; ++cnt[x];
        now = now - 1ll * temp * (temp - 1) + 1ll * temp * cnt[x];
    }
    
    void del(int x) {
        int temp = cnt[x]; --cnt[x];
        now = now - 1ll * temp * (temp - 1) + 1ll * cnt[x] * (cnt[x] - 1);
    }
    
    int main() {
        scanf("%d %d", &n, &m), sqrn = n / sqrt(m);
        for (int i = 1; i <= n; ++i) {
            scanf("%d", &a[i]);
            num[i] = (i - 1) / sqrn + 1;
        }
        for (int i = 1; i <= m; ++i) {
            scanf("%d %d", &q[i].x, &q[i].y);
            q[i].id = i, q[i].len = q[i].y - q[i].x + 1;
        }
        std::sort(q + 1, q + m + 1);
        int l = 1, r = 1; cnt[a[1]] = 1;
        for (int i = 1; i <= m; ++i) {
        	while (l > q[i].x) add(a[--l]);
            while (r < q[i].y) add(a[++r]);
            while (l < q[i].x) del(a[l++]);
            while (r > q[i].y) del(a[r--]);
            if (now == 0) fz[q[i].id] = 0, fm[q[i].id] = 1;
            else {
                ll g = gcd(now, 1ll * q[i].len * (q[i].len - 1));
                fz[q[i].id] = now / g, fm[q[i].id] = 1ll * q[i].len * (q[i].len - 1) / g;
            }
        }
        for (int i = 1; i <= m; ++i) {
            if (fz[i] == 0) fm[i] = 1;
            printf("%lld/%lld
    ", fz[i], fm[i]);
        }
        return 0;
    }
    
  • 相关阅读:
    异步解决方案----Promise与Await
    多页应用 Webpack4 配置优化与踩坑记录
    左侧固定,右侧自适应的布局方式(新增评论区大佬教的方法)
    精读《Epitath 源码
    如何编写 Typescript 声明文件
    状态码具体解释
    LINQ体验(2)——C# 3.0新语言特性和改进(上篇)
    kafka教程
    double x = 10 ,y = 0;y = x % 2; 这个表达式正确吗?
    mongodb mapreduce使用总结
  • 原文地址:https://www.cnblogs.com/poi-bolg-poi/p/13902662.html
Copyright © 2011-2022 走看看