UVA - 11235 RMQ

UVA - 11235

题意:给出一个非降序的整数数组,你的任务是对于一系列询问,回答区间内出现最多的值的次数。

tags: 大白书的题果然有意思,智商不够用了

1】注意给出的是非降序的数组,那么相同的数是连在一起的。所以我们可以先游程编码,即比如 -1 -1 1 1 1 1 3 10 10 10  变为  (1,2) 、(2,4)、(3,1)、(4,3)。

2】然后询问 l, r , 如果 l, r 在同一个块里,就直接减;否则,答案就是 max( 左边块占有的长度,右边块占有的长度,中间所有块的最大值 )。  而中间所有块的最大值用 RMQ 解决。

#include<bits/stdc++.h>
using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
#define rep(i,a,b) for (int i=a; i<=b; ++i)
#define per(i,b,a) for (int i=b; i>=a; --i)
#define mes(a,b)  memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
#define MP make_pair
#define PB push_back
#define fi  first
#define se  second
typedef long long ll;
const int N = 100005;

int n, q, cnt, a[N], f[N][30];
pair< int, int > p[N];
void Init_RMQ()
{
    rep(i,1,cnt) f[i][0]=p[i].se;
    for(int j=1; (1<<j)<=cnt; ++j)
        for(int i=1; i+(1<<j)-1<=cnt; ++i)
            f[i][j] = max(f[i][j-1], f[i+(1<<(j-1))][j-1]);
}
int query(int l, int r)
{
    if(r-l+1<=0) return 0;
    int lg = floor(log2(r-l+1));
    return max(f[l][lg], f[r-(1<<lg)+1][lg]);
}
int id[N], num[N];
int solve(int ql, int qr)
{
    int idl=id[ql], idr=id[qr];
    if(idl==idr) return qr-ql+1;
    return max(num[idl]-ql+1, max(qr-num[idr-1], query(idl+1,idr-1)));
}
int main()
{
    while(~scanf("%d", &n), n)
    {
        scanf("%d", &q);
        cnt = 0;
        a[0]=INF;
        rep(i,1,n)
        {
            scanf("%d", &a[i]);
            if(a[i]!=a[i-1]) p[++cnt]=MP(a[i],1), num[cnt]=num[cnt-1]+1;
            else ++p[cnt].se, ++num[cnt];
            id[i] = cnt;
        }
        Init_RMQ();
        int ql, qr;
        while(q--)
        {
            scanf("%d%d", &ql, &qr);
            printf("%d\n", solve(ql, qr));
        }
    }

    return 0;
}
posted @ 2018-02-19 12:10  v9fly  阅读(106)  评论(0编辑  收藏  举报