Uva11235
题目大意:
给出一个非降序排列的整数数组,对于每组询问 (l, r),给出区间 [l, r] 中出现次数最多的值的出现次数
根据题意,整个数组非降序排列,那么相同的数都会凑在一起
这样我们对于每个位置记录 3 个值:tol, tor, tot
分别代表:
和这个数相同的值向左最远延伸到 tol
和这个数相同的值向右最远延伸到 tor
和这个数相同的数共有 tot 个
这样我们就可以根据以上三个值和下标愉快的打ST表了
#include<algorithm> #include<iostream> #include<cstring> #include<cstdlib> #include<cctype> #include<cstdio> using namespace std; const int MAXN = 100005; int n, q; int a[MAXN], tol[MAXN], tor[MAXN], tot[MAXN], st[MAXN][30]; inline void ST_init() { for(int i = 1; i <= n; ++i) st[i][0] = tot[i]; for(int j = 1; (1 << j) <= n; ++j) for(int i = 1; i + (1 << j) - 1 <= n; ++i) st[i][j] = max(st[i][j - 1], st[i + (1 << (j - 1))][j - 1]); return; } inline int query(int l, int r) { if(a[l] == a[r]) return r - l + 1; int res = -100001, k = 0; res = max(res, max(tor[l] - l + 1, r - tol[r] + 1)); l = tor[l] + 1; r = tol[r] - 1; if(l > r) return res; while((1 << (k + 1)) <= r - l + 1) ++k; return max(res, max(st[l][k], st[r - (1 << k) + 1][k])); } inline void resetall() { memset(a, 0, sizeof(a)); memset(tol, 0, sizeof(tol)); memset(tor, 0, sizeof(tor)); memset(tot, 0, sizeof(tot)); memset(st, 0, sizeof(st)); return; } int main() { while(scanf("%d", &n) and n) { scanf("%d", &q); for(int i = 1; i <= n; ++i) scanf("%d", &a[i]); int totk = 0, rk = n, rnk = 0, k = 0; for(int i = 1; i <= n + 1; ++i) { if(a[i] != a[i - 1]) { int j = i - 1; while(j and !tot[j]) { tot[j--] = totk; } totk = 0; } ++totk; } ST_init(); for(int i = 1; i <= n; ++i) { if(a[i] != a[i - 1]) k = i; tol[i] = k; int rvrs = n - i + 1; if(a[rvrs] != a[rvrs + 1]) rk = rvrs; tor[rvrs] = rk; } int l, r; while(q--) { scanf("%d%d", &l, &r); if(a[l] == a[r]) printf("%d\n", r - l + 1); else printf("%d\n", query(l ,r)); } resetall(); } return 0; }
禁止诸如开发者知识库/布布扣/码迷/学步园/马开东等 copy 他人博文乃至博客的网站转载
,用户转载请注明出处:https://www.cnblogs.com/xcysblog/