zoukankan      html  css  js  c++  java
  • 分桶法和平方分割

    分桶法:把一排物品或者平面分成桶,每个桶分别维护自己内部的信息,已到达高效计算的目的的方法。

    其中,平方分割是把排成一排的n个元素每√n个分在一个桶内进行维护的方法的统称。这样的方法可以使对区间的操作复杂度降至O(√n)。

    以RMQ为例:

    基于平方分割的RMQ

    给定一个数列a1,a2,a3,a4,a5,a6,....,an,目标是在O(√n)浮渣度内实现以下两个功能

    • 给定s,t,求as,as+1,as+2,...,at的最小值。
    • 给定i,x,把ai的值变成x。

    基于平方分割的RMQ预处理

    令len=(int)(√n),把a中的元素每len个分成一个桶,并且计算出每个桶内的最值。

    基于平方分割的RMQ查询

    如下图所示,查询

    • 如果桶完全包含在区间内,则查询桶内的最小值。
    • 如果元素所在的桶不完全被包含包含,则逐个检查最值。

    它们的最值就是区间的最值了。

    基于平方分割的RMQ的值的更新

    在更新元素的值时,只需要更新该元素所在的桶的最值。

    基于平方分割的RMQ的复杂度

    在更新时,因为每个桶内有len个元素,所以复杂度是O(len)=√n

    而在查询时

    • 完全包含在区间内的桶的个数是O(n/len)
    • 所在的桶不被区间完全包含的元素个数是O(len)

    因为len=O(√n),所以操作复杂度是O(n/len+len)=O(√n+√n)=O(√n

    附上POJ 3246.Balanced Lineup的平方分割的RMQ写法

    代码:

    #include <iostream>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    #include<map>
    #include<queue>
    #include<stack>
    #include<vector>
    #include<set>
    using namespace std;
    #define PI acos(-1.0)
    typedef long long ll;
    typedef pair<int,string> P;
    const int maxn=1e5+100,maxm=1e5+100,inf=0x3f3f3f3f,mod=1e9+7;
    const ll INF=1e13+7;
    priority_queue<P,vector<P>,greater<P> >q;
    struct edge
    {
        int from,to;
        int cost;
    };
    ///分桶法+平方分割解决RMQ问题
    struct node
    {
        int l,r;
        int mmin,mmax;
    } sign[maxn];
    int a[maxn];
    int main()
    {
        int n,q;
        scanf("%d%d",&n,&q);
        int x=(int)(sqrt(n));
        int t=0;
        for(int i=1; i<=n; i++)
        {
            scanf("%d",&a[i]);
            if(i%x==1) t++,sign[t].l=i,sign[t].r=i,sign[t].mmax=0,sign[t].mmin=inf;
            sign[t].mmin=min(sign[t].mmin,a[i]);
            sign[t].mmax=max(sign[t].mmax,a[i]);
            sign[t].r=i;
        }
        while(q--)
        {
            int l,r;
            scanf("%d%d",&l,&r);
            int mmax=0,mmin=inf;
            for(int i=1; i<=t; i++)
            {
                if(l>sign[i].r) continue;
                if(l>sign[i].l)
                {
                    for(int j=l; j<=sign[i].r&&j<=r; j++)
                        mmax=max(mmax,a[j]),mmin=min(mmin,a[j]);
                }
                else if(l<=sign[i].l&&sign[i].r<=r)
                    mmax=max(mmax,sign[i].mmax),mmin=min(mmin,sign[i].mmin);
                else if(r<sign[i].r)
                {
                    for(int j=sign[i].l; j<=r; j++)
                        mmax=max(mmax,a[j]),mmin=min(mmin,a[j]);
                }
                if(r<=sign[i].r) break;
            }
            cout<<mmax-mmin<<endl;
        }
        return 0;
    }
    平方分割的RMQ
  • 相关阅读:
    Linux Sever简单笔记(第十二堂课)之linux下的系统故障分析和排查
    Linux Sever简单笔记(第十一堂课)之linux下的备份和恢复及rsync还有inotify和dump以及restore
    Linux Sever简单笔记(第十堂课)之linux下的任务计划及相关的命令
    ubuntu18.04设置apt源(国内)
    shell简单常用脚本实例
    装完ubuntu系统之后,不能ssh正常连接
    mysql主从复制以及读写分离
    复习计划
    linux下dhcp的安装及配置
    日常问题
  • 原文地址:https://www.cnblogs.com/GeekZRF/p/7136623.html
Copyright © 2011-2022 走看看