http://poj.org/problem?id=3368
思路:
由于序列是非降的,把相同元素视作一个区间,然后统计出每个区间的左端点left和右端点right,再用线段树维护区间长度的最大值
记待查询区间[a,b]的a对应的区间为intera,b对应的区间为interb,则当interb==intera时,最大频率为b-a+1;当interb>intera时,最大频率为max(max(right[intera] - a + 1, b - left[interb] + 1), query(intera + 1, interb - 1, root)))
完整代码:
/*UVa: 0.225s*/
/*POJ: 1250ms,1648KB*/
#include<cstdio>
#include<algorithm>
using namespace std;
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1
#define root 0, cnt, 1
const int mx = 100005;
int maxs[mx << 2], left[mx], right[mx], interval[mx], ii;
inline void pushup(int rt)
{
maxs[rt] = max(maxs[rt << 1], maxs[rt << 1 | 1]);
}
void build(int l, int r, int rt)
{
if (l == r)
{
maxs[rt] = right[ii] - left[ii] + 1;
++ii;
return;
}
int m = (l + r) >> 1;
build(lson);
build(rson);
pushup(rt);
}
int query(int ql, int qr, int l, int r, int rt)
{
if (ql <= l && r <= qr)
{
return maxs[rt];
}
int maxs = 0, m = (l + r) >> 1;
if (ql <= m) maxs = query(ql, qr, lson);
if (m < qr) maxs = max(maxs, query(ql, qr, rson));
return maxs;
}
int main()
{
int n, q, val, cnt, i, x, a, b, intera, interb;
while (scanf("%d%d", &n, &q), n)
{
val = -mx, cnt = -1;
for (i = 1; i <= n; ++i)
{
scanf("%d", &x);
if (x != val) val = x, ++cnt, left[cnt] = right[cnt] = i;
else ++right[cnt];
interval[i] = cnt;
}
ii = 0;
build(root);
while (q--)
{
scanf("%d%d", &a, &b);
intera = interval[a], interb = interval[b];
if (interb == intera) printf("%d\n", b - a + 1);
else if (interb == intera + 1) printf("%d\n", max(right[intera] - a + 1, b - left[interb] + 1));
else printf("%d\n", max(max(right[intera] - a + 1, b - left[interb] + 1), query(intera + 1, interb - 1, root)));
}
}
return 0;
}