zoukankan      html  css  js  c++  java
  • Uva 11235 RMQ问题

    RMQ:

    有一个不变的数组,不停的求一个区间的最小值。

    使用倍增的思想优化到logN;

    d(i,j) 表示从 i 开始的,长度为2j的一段元素中的最小值。

    那么状态转移方程:

    d(i,j) = min{ d(i,j-1) ,  d(i+2j-1,j-1) } 

    题目链接:https://vjudge.net/contest/146667#problem/B

    题意:一个非降序的数组,询问(i,j)中出现次数最多的数值,所对应的出现次数是多少。

    分析:

    进行游戏编码,value[i] 和count[i] 表示第 i 段对应的数值和出现的次数,

    num[i] 表示位置 i 对应的段所在的编号,left[i] 表示 i 位置所在的段的左端点,right[i] 右端点。

    那么(L,R)就是分成3个部分。

    一个是right[L] - L + 1,R-left[R] + 1,还一个就是RMQ(count,num[L]+1,num[R]-1)。

    特殊情况:如果L和R在同一段里面,R-L+1;

    Source Code:

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<vector>
     4 using namespace std;
     5 
     6 const int maxn = 100000 + 5;
     7 const int maxlog = 20;
     8 
     9 // 区间最*大*值
    10 struct RMQ
    11 {
    12     int d[maxn][maxlog];
    13     void init(const vector<int>& A)
    14     {
    15         int n = A.size();
    16         for(int i = 0; i < n; i++) d[i][0] = A[i];
    17         for(int j = 1; (1<<j) <= n; j++)
    18             for(int i = 0; i + (1<<j) - 1 < n; i++)
    19                 d[i][j] = max(d[i][j-1], d[i + (1<<(j-1))][j-1]);
    20     }
    21 
    22     int query(int L, int R)
    23     {
    24         int k = 0;
    25         while((1<<(k+1)) <= R-L+1) k++; // 如果2^(k+1)<=R-L+1,那么k还可以加1
    26         return max(d[L][k], d[R-(1<<k)+1][k]);
    27     }
    28 };
    29 
    30 int a[maxn], num[maxn], left[maxn], right[maxn];
    31 RMQ rmq;
    32 
    33 
    34 int main()
    35 {
    36     int n,q;
    37     while(scanf("%d%d",&n,&q)==2)
    38     {
    39         for(int i=0; i<n; i++)
    40             scanf("%d",&a[i]);
    41 
    42         a[n] = a[n-1] + 1;
    43         int start = -1;
    44         vector<int> count;
    45         for(int i=0; i<=n; i++)
    46         {
    47             if(i==0||a[i]>a[i-1])
    48             {
    49                 if(i>0)
    50                 {
    51                     count.push_back(i-start);
    52                     for(int j=start;j<i;j++) {
    53                         num[j] = count.size()-1;
    54                         left[j] = start;
    55                         right[j] = i-1;
    56                     }
    57                 }
    58                 start = i;
    59             }
    60         }
    61 
    62         rmq.init(count);
    63         while(q--) {
    64             int L,R,ans;
    65             scanf("%d%d",&L,&R);
    66             L--;
    67             R--;
    68             if(num[L]==num[R]) ans = R - L + 1;
    69             else {
    70                 ans = max(R-left[R]+1,right[L]-L+1);
    71                 if(num[L]+1<num[R])
    72                     ans = max(ans,rmq.query(num[L]+1,num[R]-1));
    73             }
    74             printf("%d
    ",ans);
    75         }
    76     }
    77     return 0;
    78 }
    View Code
  • 相关阅读:
    破解 inode 校园网多网卡限制方法
    更改 eclipse的 workplace路径
    VMware Network Adapter VMnet1和VMnet8 未识别的网络的解决方法
    eclipse更改xml文件,txt文件,property文件等文件编辑器的字体设置
    Lua中数组全排序
    Lua尾调用
    C++ 调用Lua简单例子
    linux生成core dump
    vc获取系统日期
    C++培训第一天
  • 原文地址:https://www.cnblogs.com/TreeDream/p/6297798.html
Copyright © 2011-2022 走看看