时间限制:3.000秒
这次是Sparse-Table算法版本的修改版,改用线段树解决了RMQ问题,顺带验证下自己写的线段树模版管不管用。
题目是回答一系列询问,求一段非降序排列的数组中某一段中出现次数最多的数出现的次数。
先进行游程编码,例如-啊,-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 SegTree { // Segment Tree
private:
static const int MAXN = 10240000; // 数组的两倍长
static const int inf = -1;
private:
int minv[MAXN], len;
private:
int query(const int &L, const int &R, const int &o, const int &l, const int &r) const {
int m = l + (r - l) / 2, ans = inf;
if(L <= l && r <= R) return minv[o];
if(L <= m) ans = max(ans, query(L, R, o*2, l, m));
if(m < R) ans = max(ans, query(L, R, o*2+1, m+1, r));
return ans;
}
void update(const int &p, const int &v, const int &o, const int &l, const int &r) {
int m = l + (r - l) / 2;
if(l == r) minv[o] = v;
else {
if(p <= m) update(p, v, o*2, l, m);
else update(p, v, o*2+1, m+1, r);
minv[o] = max(minv[o*2], minv[o*2+1]);
}
}
void init(const int *A, const int &o, const int &l, const int &r) {
if(l == r) minv[o] = A[l];
else {
int m = l + (r - l) / 2;
init(A, o*2, l, m);
init(A, o*2+1, m+1, r);
minv[o] = max(minv[o*2], minv[o*2+1]);
}
}
public:
int init(const int *A, const int &length) { init(A, 1, 1, len = length); }
int query(const int &L, const int &R) { return query(L, R, 1, 1, len); }
void update(const int &p, const int &v) { return update(p, v, 1, 1, len); }
};
const int MAXN = 100000 + 10;
int n, q;
int a[MAXN], p[MAXN], left[MAXN], right[MAXN];
int s[MAXN], len;
SegTree tree;
inline void push() {
len = 1;
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;
}
}
}
int main() {
while(~scanf("%d", &n) && n) {
scanf("%d", &q);
for(int i = 0; i != n; ++i) scanf("%d", &a[i]);
push();
tree.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(tree.query(l + 1, r - 1), temp));
}
}
}
}