UVA - 11235 Frequent values 频繁出现的数值(RMQ)

大体题意:

给你n 个元素的非降序排列的数组,给你m 个询问i,j,求出 区间[i,j]内出现次数最多数的次数!

思路:

RMQ算法是求某个区间内的最小值或最大值!

这个问题关键是转换到RMQ问题上去!

因为数组呈非降序,所以所有相等的元素会聚在一起!

所以可以把数组分成一块一块的, val[i]表示第i块 数值是多少,cot[i]表示第i块出现了多少次!

num[p]表示数组位置p 属于哪一块,left[p],right[p]分别表示位置p所在块的  左边位置和右边位置!

那么只需统计 num[l] + 1 到 num[r] - 1 这些块中cot最大值是多少,在哪这个答案和边界进行比较!

边界时第L段 他有right[l]-l+1个     和R所在的段   有 r-left[r]+1个!

注意右边一定要大于左边的问题!

注意有个特殊情况,如果L和R在同一段,答案是R-L+1

详细见代码:

#include
#include
#include
using namespace std;
const int maxn = 100000 + 10;
const int inf = 0x3f3f3f3f;
int num[maxn],left[maxn],right[maxn],val[maxn],cot[maxn],a[maxn];
int n,m;
int cur;
int d[maxn][30];
void RMQ_init(){
    for (int i = 0; i < cur; ++i)d[i][0] = cot[i];
    for (int j = 1; (1<= i; --k){
                right[k] = j-1;
            }
            ++cur;
            i = j-1;
        }
        RMQ_init();
        for (int i = 0; i < m; ++i){
            int l,r;
            scanf("%d %d",&l,&r);
            l--;r--;
            if (num[l] == num[r]){
                printf("%d\n",r-l+1);
                continue;
            }
            int t1 = num[l]+1;
            int t2 = num[r]-1;
//            printf("t1 = %d,t2 = %d\n",t1,t2);

            int t_ans;
            if (t2 >= t1)
                t_ans = RMQ(t1,t2);
            else t_ans = 0;
//            printf("%d\n",right[l]);
            int ans = max(max(t_ans,right[l]-l+1),r-left[r]+1);
            printf("%d\n",ans);
        }
    }
    return 0;
}
/*
10 3
-1 -1 1 1 1 1 3 10 10 10
*/


你可能感兴趣的:(算法竞赛入门经典,训练指南,RMQ算法)