HDU1806 Frequent values

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU1806 Frequent values相关的知识,希望对你有一定的参考价值。

题解:

注意数组a是非降序排列。

所以将a数组转化出现次数的数组b

例如 -1 -1 2 3 对应 2 2 1 1

那么每次查询,分为左边,右边和中间三部分,

预处理每个数对应的左右范围.可以用map,也可以用二分。

代码:

//二分处理
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<map>
#include<set>
#include<vector>
using namespace std;
using namespace std;
#define pb push_back
#define mp make_pair
#define se second
#define fs first
#define ll long long
#define MS(x,y) memset(x,y,sizeof(x))
#define MC(x,y) memcpy(x,y,sizeof(x))
#define ls o<<1
#define rs o<<1|1
#define SZ(x) ((int)(x).size())
#define FOR(it,c) for(__typeof((c).begin()) it=(c).begin();it!=(c).end();it++)
typedef pair<int,int> P;
const double eps=1e-9;
const int maxn=100100;
const int N=1e9;
const int mod=1e9+7;

ll read()
{
    ll x=0,f=1;char ch=getchar();
    while(ch<0||ch>9){if(ch==-)f=-1;ch=getchar();}
    while(ch>=0&&ch<=9){x=x*10+ch-0;ch=getchar();}
    return x*f;
}
//-----------------------------------------------------------------------------

int a[maxn],b[maxn],mx[maxn][20];
int n,m,k,l,r;
map<int,int> Num;

void rmq_init()
{
    for(int i=1;i<=n;i++) mx[i][0]=b[i];
    k=(int)(log(n*1.0)/log(2.0));
    for(int i=1;i<=k;i++)
    for(int j=1;j<=n;j++){
        mx[j][i]=mx[j][i-1];
        if(j+(1<<(i-1))<=n) mx[j][i]=max(mx[j][i],mx[j+(1<<(i-1))][i-1]);
    }
}

int rmq_max(int l,int r)
{
    k=(int)(log((r-l+1.0)*1.0)/log(2.0));
    return max(mx[l][k],mx[r-(1<<k)+1][k]);
}

int bs_left(int l)
{
    int L=1,R=l,Goal=l;
    while(L<=R){
        int M=(L+R)>>1;
        if(a[M]==a[l]){
            Goal=M;
            R=M-1;
        }
        else L=M+1;
    }
    return Goal;
}

int bs_right(int r)
{
    int L=r,R=n,Goal=r;
    while(L<=R){
        int M=(L+R)>>1;
        if(a[M]==a[r]){
            Goal=M;
            L=M+1;
        }
        else R=M-1;        
    }
    return Goal;
}

int main(){
    while(scanf("%d",&n)&&n){
        scanf("%d",&m);
        Num.clear();
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
            Num[a[i]]++;
        }
        for(int i=1;i<=n;i++) b[i]=Num[a[i]];
        rmq_init();
        for(int i=1;i<=m;i++){
            scanf("%d%d",&l,&r);
            if(a[l]==a[r]) printf("%d\n",r-l+1);
            else{
                int L_max=bs_right(l)-l+1;
                int R_max=r-bs_left(r)+1;
                int M_max=0;
                if(bs_right(l)+1<=bs_left(r)-1) M_max=rmq_max(bs_right(l)+1,bs_left(r)-1);
                printf("%d\n",max(max(L_max,R_max),M_max));
            }
        }
    }
    return 0;
}

 

以上是关于HDU1806 Frequent values的主要内容,如果未能解决你的问题,请参考以下文章

[HDOJ1806]Frequent values(RMQ,ST)

POJ 3368 Frequent values(线段树区间合并)

(线段树区间合并)UVA 11235 - Frequent values

POJ 3368 Frequent values(RMQ)

UVA 11235 Frequent values RMQ

Frequent values(倍增RMQ)