zoukankan      html  css  js  c++  java
  • BZOJ:2038: [2009国家集训队]小Z的袜子(hose)(莫队算法模板)

    题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=2038

    解题心得:

    • 第一次接触莫队算法,很神奇,很巧妙。莫队算法主要就是用来解决多次询问时维护区间内的信息。维护区间信息第一个想法肯定是线段树,但是线段树维护的区间信息量很少(如最大值,最小值,SUM,GCD等),接触过尺取法的人都知道有时候在处理区间询问的时候可以先将区间排序然后再尺取。莫队算法也用了类似的思维,先对询问区间进行排序,这里排序就用了分块的思想,并不是严格的按照左端点,或者右端点排序,更多的是按照分的块进行排序,这样就减少了维护区间的大幅度乱跳动。
    • 莫队的复杂度分析,每个块长度unit为sqrt(n),如果l端点不在同一个块内需要移动到另一个块内,移动次数最多为2*unit,l在一个块内,r所在位置无法确定,但是排序后可以保证是单调递增的,所以最多移动n次,总共有n/unit个块,最坏要移动n/unit个块,所以总的最坏的复杂度是O(n * sqrt(n) + n * n /sqrt(n) )
    • 这个题来说算概率还是简单的 (Sum(每种袜子个数 2 ) - (r - l + 1)) / ((r - l + 1) * (r - l)),分母可以O(1)内得到,分子可以使用莫队维护
    /**************************************************************
        Problem: 2038
        User: swust5120164059
        Language: C++
        Result: Accepted
        Time:3404 ms
        Memory:7560 kb
    ****************************************************************/
    
    //
    //      ┏┛ ┻━━━━━┛ ┻┓
    //      ┃       ┃
    //      ┃   ━   ┃
    //      ┃ ┳┛   ┗┳ ┃
    //      ┃       ┃
    //      ┃   ┻   ┃
    //      ┃       ┃
    //      ┗━┓   ┏━━━┛
    //        ┃   ┃   神兽保佑
    //        ┃   ┃   代码无BUG!
    //        ┃   ┗━━━━━━━━━┓
    //        ┃           ┣┓
    //        ┃             ┏┛
    //        ┗━┓ ┓ ┏━━━┳ ┓ ┏━┛
    //          ┃ ┫ ┫   ┃ ┫ ┫
    //          ┗━┻━┛   ┗━┻━┛
    #include <stdio.h>
    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <math.h>
    using namespace std;
    typedef long long ll;
    const int maxn = 1e5+7;
    
    struct NODE {
        ll l, r, A, B, pos;
    }q[maxn];
    
    ll n, m, color[maxn], B[maxn], cnt_color[maxn];
    
    void init() {
        scanf("%lld%lld",&n,&m);
        ll div = (ll) sqrt(n);
        for(int i=1;i<=n;i++) {
            scanf("%lld", &color[i]);
            B[i] = i/div + 1;
        }
        for(int i=0;i<m;i++) {
            scanf("%lld%lld",&q[i].l, &q[i].r);
            q[i].pos = i;
        }
    }
    
    bool cmp1(NODE a, NODE b) {
        if(B[a.l] == B[b.l])
            return a.r < b.r;
        return a.l < b.l;
    }
    
    bool cmp2(NODE a, NODE b) {
        return a.pos < b.pos;
    }
    
    ll ans = 0;
    void add(ll pos, ll va) {
        ans -= pow(cnt_color[color[pos]], 2);
        cnt_color[color[pos]] += va;
        ans += pow(cnt_color[color[pos]], 2);
    }
    
    int main() {
        init();
        sort(q, q+m, cmp1);
        int l = 1, r = 0;
        for(int i=0;i<m;i++) {
            //左右端点跳转
            while(l < q[i].l)
                add(l++, -1);
            while(l > q[i].l)
                add(--l, 1);
            while(r < q[i].r)
                add(++r, 1);
            while(r > q[i].r)
                add(r--, -1);
    
            //只有一个袜子概率为0
            if(q[i].l == q[i].r) {
                q[i].A = 0;
                q[i].B = 1;
                continue;
            }
            q[i].A = ans - (q[i].r - q[i].l + 1);
            q[i].B = (q[i].r - q[i].l + 1) * (q[i].r - q[i].l);
        }
        sort(q, q+m, cmp2);
        for(int i=0;i<m;i++) {
            ll GCD = __gcd(q[i].A, q[i].B);
            printf("%lld/%lld
    ", q[i].A/GCD, q[i].B/GCD);
        }
        return 0;
    }
  • 相关阅读:
    对开发者有用的英文网站合集
    比较全的OA系统功能模块列表
    OA系统权限管理设计方案
    OA系统启动:基础数据,工作流设计
    JS生成UUID
    java类过滤器,防止页面SQL注入
    Restful安全认证及权限的解决方案
    把表单转成json,并且name为key,value为值
    JDBC上关于数据库中多表操作一对多关系和多对多关系的实现方法
    Jquery 获取第一个子元素
  • 原文地址:https://www.cnblogs.com/GoldenFingers/p/9428584.html
Copyright © 2011-2022 走看看