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;
}

 

posted @ 2018-07-15 20:49  EvalonXing  阅读(310)  评论(0编辑  收藏  举报