UVa 11235 - Frequent values

时间限制:3.000秒

题目链接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=24&page=show_problem&problem=2176


  Sparse-Table算法入门题,只不过这里的最小值变成了最大值。

  题目是回答一系列询问,求一段非降序排列的数组中某一段中出现次数最多的数出现的次数。

  先进行游程编码,例如-啊,-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 SparseTable { // Sparse-Table
private:
    static const int MAXN = 100000 + 10;
    int d[MAXN][(int)log2(MAXN) + 10];
public:
    void RMQ_init(int *A, const int &n) {
        for(int i = 0; i != n; ++i) d[i][0] = A[i];
        for(int j = 1; (1 << j) <= n; ++j) for(int i = 0; i + (1 << j) - 1 < n; ++i) {
            d[i][j] = max(d[i][j - 1], d[i + (1 << (j - 1))][j - 1]);
        }
    }
    int RMQ(const int &L, const int &R) const { // min{A[L], A[L+1], ... , A[R]}
        int k = 0;
        while((1 << (k + 1)) <= R - L + 1) ++k;
        return max(d[L][k], d[R - (1 << k) + 1][k]);
    }
};

const int MAXN = 100000 + 10;

int n, q;
int a[MAXN], p[MAXN], left[MAXN], right[MAXN];
int s[MAXN], len;
SparseTable table;

inline void push() {
    len = 0;
    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;
        }
    }
    ++len;
}

int main() {
    while(~scanf("%d", &n) && n) {
        scanf("%d", &q);
        for(int i = 0; i != n; ++i) scanf("%d", &a[i]);
        push();
        table.RMQ_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(table.RMQ(l + 1, r - 1), temp));
            }
        }
    }
}

     
     
    
    
   
   

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值