频数

 

给你 n 个整数 A1,A2,⋯ ,An组成的非降序列。

除此之外,还给你一些由整数 i 和 j(1≤i≤j≤n)组成的查询。对于每个查询,确定在 Ai,⋯ ,Aj中出现次数最多数的频数。

Format
Input
多组数据,读入到0结尾

对于每组数据

第一行包含两个整数 n 和 q。

接下来的一行包含 n 个用空格隔开的整数 A1,⋯ ,An(−100000≤Ai≤100000,i∈{1,2,⋯ ,n})格隔开。

你可以确定,对于每个 i∈{1,⋯ ,n−1},Ai≤Ai+1

以下 q 行每行一个查询,包含两个整数 i 和 j(1≤i≤j≤n),表明查询的边界。

1≤n,q≤100000间。

Output
对于每个查询,输出一行,一个整数,即在给定范围内出现次数最多数的频数。

Samples
输入数据 1
10 3
-1 -1 1 1 1 1 3 10 10 10
2 3
1 10
5 10
0
输出数据 1
1
4
3

 

 

Sol:

int a[maxn];//读入进来的数字
int sum[maxn];//以第i个位置为止,其代表的数字出现了多少次
int num[maxn];//对读入的数字进行离散化操作,化成1,2,3.....这样的数列
int last[maxn];//last[i]代表第i个位置,它可能向右延伸,记录它最后出现的位置
int f[maxn][22];//针对sum数列建立st表

 

 

 

 

最后,考虑到由于给定的区间,有可能中间某个数字,也就有同一类数字可能有一些在这个区间内,有一些却不在这个区间内。

 

分成下面两种情况

1:给定的区间内只有一种数字

 

2:给定的区间内有多种数字,则挖出第一段的出来。因为它有可能是我们上面所说的“不完整“的。

后面的则rmq算法进行查询。

  

首先用结构体保存元素值X,根据元素值的不同,将同一个值用一个POS下标记录:
-1 -1 1 1 1 1 3 10 10 10 就被记录为 0 0 1 1 1 1 2 3 3 3

然后对元素进行离散化,用一个新的数组R记录每个元素当前出现的次数:
-1 -1 1 1 1 1 3 10 10 10 就被记录为 1 2 1 2 3 4 1 1 2 3

由于给定的区间,有可能中间某个数字,也就有同一类数字可能有一些在这个区间内,有一些却不在这个区间内。

这个其实也是有两种情况

1:前面一段没划在这个区间内,于是其信息不好确定

2:后面一段没划在这个区间内,这个我们在最开始处理时,可以弄出来的。

 

 

 

  

posted @ 2022-03-02 15:40  我微笑不代表我快乐  阅读(8)  评论(0编辑  收藏  举报