zoukankan      html  css  js  c++  java
  • UVA 11235 频繁出现的数值 RMQ

    题目链接:

    http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2176

    RMQ,就是范围最小值的缩写,这个算法是Tarjan 的 Sparse-Table 算法,复杂度为O(n*log(n)).

    就是用数组d[i][j]表示范围[i,i+2^j-1]中的最小值。

    然后有递推式

    d[i][j] = min(d[i][j-1],d[i+2^(j-1)][j-1]).

    有边界条件d[i][0] = A[i].

    然后就能求出所有的d[i][j].查询时只需找出2^(k+1) <= R-L+1的最大的k值,取等号时,k要+1.

    答案为min(d[L][k],d[R-(1<<k)+1][k]).这两个区间有重叠,木有关系的,不是吗?

    本题用Sparse-Table算法,改成求最大值即可。具体解法采用游程编码。

    如输入的数组为-1,-1,1,1,1,1,3,10,10,10.则能得到(-1,2),(1,4),(3,1),(10,3),(a,b)表示值为a的数有b个。

    然后将数组分为4块,编号分别为1,2,3,4.用辅助数组num[i],left[i],right[i]记录位置i所在的块的编号,以及块的左端点和右端点位置。

    数组   -1,-1,1,1,1,1,3,10,10,10.

    num   1,  1,2,2,2,2,3,4,  4,  4.

    left     1 , 1,3,3,3,3,7,8,  8,  8.

    right   2, 2,6, 6,6,6,7,10,10,10

    然后答案为max(right(L)-L+1 , R - left[R]+1, max (num[L]+ 1, num[R] - 1));

    特判当L和R在同一段时答案是R-L+1.

    当num[L]+1 > num[R]-1时,最大值为负无穷。

    贴代码:

     1 #include<cstdio>
     2 #include<algorithm>
     3 using namespace std;
     4 const int N =100005;
     5 int c;
     6 //元素从1编到n
     7 int d[N][30],n,cnt[N],num[N],left[N],right[N];
     8 void RMQ_init()
     9 {
    10     for(int i=1; i<=c; ++i) d[i][0] = cnt[i];
    11     for(int j=1; (1<<j) <= c; ++j)
    12         for(int i=1; i+j-1<=c; ++i)
    13             d[i][j] = max(d[i][j-1],d[i+(1<<(j-1))][j-1]);
    14 }
    15 int RMQ(int L,int R)
    16 {
    17     if(L>R) return 0;
    18     int k=0;
    19     while((1<<(k+1)) <= R-L+1) ++k;
    20     return max(d[L][k],d[R-(1<<k)+1][k]);
    21 }
    22 int main()
    23 {
    24 //    freopen("in.txt","r",stdin);
    25     int n,Q,a;
    26     while(scanf("%d",&n),n)
    27     {
    28         for(int i=0; i<=n; ++i) cnt[i]=0;
    29         scanf("%d%d",&Q,&a);
    30         int p = a;
    31         c=1,cnt[c] = 1,num[1] = c;
    32         for(int i=2; i<=n; ++i)
    33         {
    34             scanf("%d",&a);
    35             if(a != p)
    36             {
    37                 p = a;
    38                 ++c;
    39             }
    40             ++cnt[c];
    41             num[i] = c;
    42         }
    43         int s =0;
    44         for(int i=1; i<=c; ++i)
    45         {
    46             for(int j=1; j<=cnt[i]; ++j)
    47                 left[s+j] = s+1,right[s+j] = s+cnt[i];
    48             s += cnt[i];
    49         }
    50         RMQ_init();
    51         while(Q--)
    52         {
    53             int l,r;
    54             scanf("%d%d",&l,&r);
    55             if(num[l] == num[r])
    56             {
    57                 printf("%d
    ",r-l+1);
    58                 continue;
    59             }
    60             int ans=right[l]-l+1;
    61             if(r-left[r]+1 > ans) ans = r-left[r]+1;
    62             int d = RMQ(num[l]+1,num[r]-1);
    63             if(d > ans) ans =d;
    64             printf("%d
    ",ans);
    65         }
    66     }
    67     return 0;
    68 }
    View Code
  • 相关阅读:
    MRF能量优化
    Django:model中的ForeignKey理解
    Django:常见的orm操作
    Django:在模板中获取当前url信息
    Django:haystack全文检索详细教程
    Django:全文检索功能可参考博客
    看电影学英语
    Markdown中怎么上传图片
    Mosquitto的安装、配置、测试
    Django:评论文章后局部刷新评论区
  • 原文地址:https://www.cnblogs.com/allh123/p/3289795.html
Copyright © 2011-2022 走看看