zoukankan      html  css  js  c++  java
  • UVa 11235

      题目大意:给出一个非降序排列的整数数组a[1...n],对于一系列询问(i, j),求出ai到aj中出现最多的次数。

      由于数组是非降序的,可以把数组进行游程编码(Run Length Encoding, RLE)。什么是游程编码呢,比如序列1,1,1,2,2,3,可以编码成(1,3),(2,2),(3,1),其中(a,b)表示有b个连续的a。然后就是RMQ问题了,可以使用Sqare Table算法,预处理时间为O(nlogn),每个查询只需O(1)。

      1 #include <cstdio>
      2 #include <algorithm>
      3 #include <climits>
      4 #define MAXN 100000+10
      5 using namespace std;
      6 
      7 int cnt[MAXN], num[MAXN], left[MAXN], right[MAXN];
      8 int d[MAXN][20];
      9 int n;
     10 int size;    // the size of cnt[]
     11 
     12 // read data and run length encoding
     13 void RLE()
     14 {
     15     int x, pre = INT_MAX;
     16     int cur = -1;    // the index of current segment
     17     int l;    // l is the left boundary of current segment
     18     for (int i = 0; i < n; i++)
     19     {
     20         scanf("%d", &x);
     21         if (x == pre)
     22         {
     23             cnt[cur]++;
     24             num[i] = cur;
     25             left[i] = l;
     26         }
     27         else
     28         {
     29             if (cur >= 0)
     30             {
     31                 // set the right boundary
     32                 for (int j = l; j <= i-1; j++)
     33                     right[j] = i-1;
     34             }
     35             cur++;
     36             l = i;
     37             num[i] = cur;
     38             left[i] = l;
     39             cnt[cur] = 1;
     40             pre = x;
     41         }
     42     }
     43     for (int i = l; i < n; i++)
     44         right[i] = n-1;
     45     size = cur + 1;
     46 }
     47 
     48 void RMQ_init()
     49 {
     50     int n = size;
     51     for (int i = 0; i < n; i++)
     52         d[i][0] = cnt[i];
     53     for (int j = 1; (1<<j) <= n; j++)
     54         for (int i = 0; i + (1<<j) - 1 < n; i++)
     55         {
     56             int t = i + (1<<(j-1));
     57             d[i][j] = max(d[i][j-1], d[t][j-1]);
     58         }
     59 }
     60 
     61 int RMQ(int L, int R)
     62 {
     63     if (L > R)   return 0;
     64     int k = 0;
     65     while (1<<(k+1) <= R-L+1)   k++;
     66     return max(d[L][k], d[R-(1<<k)+1][k]);
     67 }
     68 
     69 int main()
     70 {
     71 #ifdef LOCAL
     72     freopen("in", "r", stdin);
     73     //freopen("out", "w", stdout);
     74 #endif
     75     int q;
     76     while (scanf("%d%d", &n, &q) != EOF && n)
     77     {
     78         RLE();
     79         //for (int i = 0; i < size; i++)
     80         //    printf("%d ", cnt[i]);
     81         //printf("
    ");
     82         //for (int i = 0; i < n; i++)
     83         //    printf("%d	%d	%d
    ", num[i], left[i], right[i]);
     84         RMQ_init();
     85         while (q--)
     86         {
     87             int L, R;
     88             scanf("%d%d", &L, &R);
     89             L--;
     90             R--;
     91             if (num[L] == num[R])   printf("%d
    ", R-L+1);
     92             else
     93             {
     94                 int t1 = right[L]-L+1;
     95                 int t2 = R-left[R]+1;
     96                 int t3 = RMQ(num[L]+1, num[R]-1);
     97                 printf("%d
    ", max(t1, max(t2, t3)));
     98             }
     99         }
    100     }
    101     return 0;
    102 }
    View Code

      代码中cnt[i]表示第i段中有多少个数,num[i]、left[i]、right[i]分别表示位置i所在段的编号和左右端点的位置。分别考虑L和R在同一段、相邻段和中间隔若干个段的情况。

      刚开始的时候d[][]数组的第一维和第二维开得一样大,都是1000,RE了,以为开得不够大,扩大到10000,还是RE,然后就想难道要到100000,那样岂不是超出内存限制了?

    然后看别人代码,d[maxn][20]...好吧,我没考虑第二维j的取值不可能太大,没考虑清楚啊

  • 相关阅读:
    A02 React+Antdesign 创建新项目
    B02 Vue+Element 创建新项目
    B01 Vue+Element 开发环境搭建
    A01 React+Antdesign 开发环境准备
    批量处理TXT转csv
    pyinstall python文件打包成二进制exe文件
    vue前端与django后端数据交互
    页面自适应
    ETL-kettle通过java代码传递参数,调用job调用转换
    ETL-kettle基本操作,表的输入输出
  • 原文地址:https://www.cnblogs.com/xiaobaibuhei/p/3187165.html
Copyright © 2011-2022 走看看