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\n", 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\n", ans);
73         }
74     }
75 
76     return 0;
77 }
代码君

 

posted @ 2015-03-17 20:20  AOQNRMGYXLMV  阅读(156)  评论(0编辑  收藏  举报