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 }

代码君

时间: 2024-10-06 10:14:42

UVa 11235 (RMQ) Frequent values的相关文章

uva 11235(RMQ)

题意:给出非降序的n个数字的序列(有重复),然后给出i,j问[i,j]范围内出现最多次数的值的次数. 题解:经典的RMQ问题,按书上题解的思路,先把序列分段,即相同数字是一个段,用val[cnt]和count[cnt]表示第cnt段的值和出现次数,num[i],l[i],r[i]分别表示位置i所在段编号(cnt),左右端点位置,那么每次查询[i,j]时,就是要计算i到i左端点的元素个数,j到j右端点的元素个数,还有num[i] + 1到num[j] - 1段的count的最大值,这三者中的最大值

UVA 11235 RMQ算法

上次的湘潭赛的C题,用线段树敲了下还是WA,不知道为何,我已经注意了处理相同数据,然后他们当时用的RMQ. 所以学了下RMQ,感觉算法思想是一样的,RMQ用了DP或者是递推,由单个数到2^k往上推,虽然有部分重叠的,也没关系,因为RMQ是求区间最值嘛 然后这道题目,要把出现次数化为最值,构造一个新的数组来存贮出现次数,每次是在这个数组里面查询.细节处理要注意,比如所求的区间可能就在一个段里面,需要单独判断. #include <iostream> #include <cstdio>

uva 11235 - Frequent values(RMQ)

题目链接:uva 11235 - Frequent values 题目大意:给定一个非降序的整数数组,要求计算对于一些询问(i,j),回答ai,ai+1,-,aj中出现最多的数出现的次数. 解题思路:因为序列为非降序的,所以相同的数字肯定是靠在一起的,所以用o(n)的方法处理处每段相同数字的区间.然后对于每次询问: num[i]=num[j]:j?i+1 numi≠numj:max(RMQ(righti+1,reftj?1),max(righti?i+1,j?leftj+1)) #include

UVA 11235 Frequent values(RMQ)

Frequent values TimeLimit:3000Ms You are given a sequence of n integers a1 , a2 , ... , an in non-decreasing order. In addition to that, you are given several queries consisting of indices i and j (1 ≤ i ≤ j ≤ n). For each query, determine the most f

UVA 11235 Frequent values 线段树/RMQ

vjudge 上题目链接:UVA 11235 *******************************************************大白书上解释************************************************************ 题目大意:给出一个非降序排列的整数数组 a1,a2,a3,...,an,你的任务是对于一系列询问 (i, j),回答 ai,ai+1,...,aj 中出现次数最多的值所出现的次数. 输入格式:包含多组数据.每组

UVA 11235 Frequent values

1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 using namespace std; 5 6 const int maxn=100005; 7 8 int count[maxn]; 9 int num[maxn],ll[maxn],rr[maxn]; 10 int tot; 11 int d[maxn][50]; 12 13 int rmq (int l,int r){ 14 int

POJ 3368 Frequent values RMQ ST算法/线段树

                                                     Frequent values Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 15229   Accepted: 5550 Description You are given a sequence of n integers a1 , a2 , ... , an in non-decreasing order. In

POJ 3368 Frequent values (基础RMQ)

Frequent values Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 14742   Accepted: 5354 Description You are given a sequence of n integersa1 , a2 , ... , an in non-decreasing order. In addition to that, you are given several queries consi

poj 3368 Frequent values(RMQ)

1 /************************************************************ 2 题目: Frequent values(poj 3368) 3 链接: http://poj.org/problem?id=3368 4 题意: 给出n个数和Q个询问(l,r),对于每个询问求出(l,r)之 5 间连续出现次数最多的次数 6 算法: RMQ 7 思路: 借助数组f[i].表示第i位前面有f[i]个相同的数.对于 8 每个区间(l,r).暴力求前面几个