• UVa 11235 (RMQ) Frequent values


    范围最值问题,O(nlogn)的预处理,O(1)的查询。

    这个题就是先对这些数列进行游程编码,重复的元素只记录下重复的次数。

    对于所查询的[L, R]如果它完全覆盖了某些连续的重复片段,那么查询的就是这几种元素重复最多的次数,也就是RMQ。

    如果[L, R]还覆盖了某一部分边界,也要单独计算取最大值。

    还有个特殊情况就是查询区间都在某一个元素的重复片段中,答案直接就是R-L+1

     1 #include <cstdio>
     2 #include <vector>
     3 #include <algorithm>
     4 using namespace std;
     5 
     6 const int maxn = 100000 + 10;
     7 const int maxl = 20;
     8 
     9 struct RMQ
    10 {
    11     int d[maxn][maxl];
    12     void Init(const vector<int>& a)
    13     {
    14         int n = a.size();
    15         for(int i = 0; i < n; i++) d[i][0] = a[i];
    16         for(int j = 1; (1<<j) <= n; j++)
    17             for(int i = 0; i + (1<<j) - 1 < n; i++)
    18                 d[i][j] = max(d[i][j-1], d[i + (1<<(j-1))][j-1]);
    19     }
    20 
    21     int query(int L, int R)
    22     {
    23         int k = 0;
    24         while(1<<(k+1) <= R-L+1) k++;
    25         return max(d[L][k], d[R-(1<<k)+1][k]);
    26     }
    27 };
    28 
    29 int a[maxn], num[maxn], left[maxn], right[maxn];
    30 RMQ rmq;
    31 
    32 int main()
    33 {
    34     //freopen("in.txt", "r", stdin);
    35 
    36     int n, q;
    37     while(scanf("%d%d", &n, &q) == 2)
    38     {
    39         for(int i = 0; i < n; i++) scanf("%d", &a[i]);
    40         a[n] = a[n-1] + 1;
    41         vector<int> count;
    42         for(int i = 0; i < n; )
    43         {
    44             int j = i;
    45             while(a[j] == a[i]) j++;
    46             count.push_back(j-i);
    47             for(int k = i; k < j; k++)
    48             {
    49                 num[k] = count.size() - 1;
    50                 left[k] = i;
    51                 right[k] = j - 1;
    52             }
    53             i = j;
    54         }
    55 
    56         //for(int i = 0; i < count.size(); i++) printf("%d
    ", count[i]);
    57 
    58         rmq.Init(count);
    59         while(q--)
    60         {
    61             int L, R, ans;
    62             scanf("%d%d", &L, &R); L--; R--;
    63             if(num[L] == num[R]) ans = R - L + 1;
    64             else
    65             {
    66                 ans = max(right[L]-L+1, R-left[R]+1);
    67                 if(num[L] + 1 < num[R])
    68                 {
    69                     ans = max(ans, rmq.query(num[L]+1, num[R]-1));
    70                 }
    71             }
    72             printf("%d
    ", ans);
    73         }
    74     }
    75 
    76     return 0;
    77 }
    代码君
  • 相关阅读:
    汇编指令(它不区分大小写)
    汇编
    LINUX命令
    LInux 终端命令
    回文串的Manacher算法
    hdu3336 Counting the string kmp的next数组的应用
    hdu2203kmp匹配
    hdu2087kmp模板练习
    hdu1171kmp果题
    hdu1686kmp果题
  • 原文地址:https://www.cnblogs.com/AOQNRMGYXLMV/p/4345454.html
Copyright © 2020-2023  润新知