http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=501&page=show_problem&problem=2176
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; }