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 }
代码君

 

你可能感兴趣的:(value)