时间限制:3.000秒
Sparse-Table算法入门题,只不过这里的最小值变成了最大值。
题目是回答一系列询问,求一段非降序排列的数组中某一段中出现次数最多的数出现的次数。
先进行游程编码,例如-啊,-1,1,1,2,2,2,4可以编码成(-1, 1),(1, 2),(2, 3),(4, 1),记录下编码之后的数组每个下标对应原始数组的哪一段和原始数组的位置对应编码后数组的位置。查询时如果L和R在同一段中,结果为R-L+1,如果L和R在相邻的段中,则是L到L所在段结束位置元素个数和R所在段起始位置到R元素个数的最大值,如果L和R并非上面两种情况,则是L到L所在段结束位置元素个数,R所在段起始位置到R元素个数,L所在段和R所在段中间几段中的最大值,这三者中的最大值。
#include
#include
#include
using std::min;
using std::max;
class SparseTable { // Sparse-Table
private:
static const int MAXN = 100000 + 10;
int d[MAXN][(int)log2(MAXN) + 10];
public:
void RMQ_init(int *A, const int &n) {
for(int i = 0; i != n; ++i) d[i][0] = A[i];
for(int j = 1; (1 << j) <= n; ++j) for(int i = 0; i + (1 << j) - 1 < n; ++i) {
d[i][j] = max(d[i][j - 1], d[i + (1 << (j - 1))][j - 1]);
}
}
int RMQ(const int &L, const int &R) const { // min{A[L], A[L+1], ... , A[R]}
int k = 0;
while((1 << (k + 1)) <= R - L + 1) ++k;
return max(d[L][k], d[R - (1 << k) + 1][k]);
}
};
const int MAXN = 100000 + 10;
int n, q;
int a[MAXN], p[MAXN], left[MAXN], right[MAXN];
int s[MAXN], len;
SparseTable table;
inline void push() {
len = 0;
s[len] = 1, p[0] = len, left[len] = 0;
for(int i = 1; i != n; ++i) {
if(a[i] == a[i - 1]) ++s[len], p[i] = len;
else {
right[len++] = i - 1;
s[len] = 1, p[i] = len, left[len] = i;
}
}
++len;
}
int main() {
while(~scanf("%d", &n) && n) {
scanf("%d", &q);
for(int i = 0; i != n; ++i) scanf("%d", &a[i]);
push();
table.RMQ_init(s, len);
for(int i = 0; i != q; ++i) {
int L, R;
scanf("%d%d", &L, &R);
int l = p[--L], r = p[--R];
if(l == r) printf("%d\n", R - L + 1);
else if(l + 1 == r) printf("%d\n", max(right[l] - L + 1, R - left[r] + 1));
else {
int temp = max(right[l] - L + 1, R - left[r] + 1);
printf("%d\n", max(table.RMQ(l + 1, r - 1), temp));
}
}
}
}