寒假刷題21:Frequent values(UVA - 11235)RMQ

題目鏈接:

Frequent values

題目解析:

因爲數組是非降序的,所以首先對其進行遊程編碼(RLE)。比如-1,1,1,2,2,2,4,遊程編碼後變爲(-1,1),(1,2),(2,3),(4,1).即(a,b)表示a個連續的b

用value[]和count[]兩個數組分別表示每一段的值和出現次數,num[]、left[]、right[]分別表示當前位置所在段的編號和左右端點位置。那麼查詢(L,R)的結果即爲以下三個部分的最大值:right[L]-L+1,R-left[R]+1,中間第num[L]+1段到num[R]-1段的count最大值

怎麼求這個數組範圍最大值(RMQ)呢?可以用Sparse-Table算法,它可以以O(nlogn)的時間預處理,並以O(1)查詢

(其中d數組大小爲d[n][logn])

void RMQ_init()
{
    for(int i=1;i<=sum;i++) d[i][0]=Count[i];
    for(int j=1;(1<<j)<=sum;j++)
        for(int i=1;i+(1<<j)-1<=n;i++)
            d[i][j]=max(d[i][j-1],d[i+(1<<j-1)][j-1]);
}
int RMQ(int l,int r)
{
    int k=0;
    while((1<<(k+1))<=r-l+1) k++;
    return max(d[l][k],d[r-(1<<k)+1][k]);
}

AC(vjudge又雙炸了應該能AC吧)代碼:

#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;

int value[100010],Count[100010],n,q;
int d[100010][7];
int num[100010],Left[100010],Right[100010],sum=0;
void RMQ_init()
{
    for(int i=1;i<=sum;i++) d[i][0]=Count[i];
    for(int j=1;(1<<j)<=sum;j++)
        for(int i=1;i+(1<<j)-1<=n;i++)
            d[i][j]=max(d[i][j-1],d[i+(1<<j-1)][j-1]);
}
int RMQ(int l,int r)
{
    int k=0;
    while((1<<(k+1))<=r-l+1) k++;
    return max(d[l][k],d[r-(1<<k)+1][k]);
}
int main()
{
    while(scanf("%d",&n) && n)
    {
        cin>>q;
        int x;
        value[0]=100001;
        for(int i=1;i<=n;i++)
        {
            cin>>x;
            if(x!=value[sum])
            {
                Right[sum]=i-1;
                sum++;
                Left[sum]=i;
                value[sum]=x;
                Count[sum]=1;
                num[i]=sum;
            }
            else
            {
                Count[sum]++;
                num[i]=sum;
            }
        }
        Right[sum]=n;
        RMQ_init();
        //cout<<RMQ(1,1);
        for(int i=1;i<=q;i++)
        {
            int l,r;
            cin>>l>>r;
            if(num[l]==num[r]) {cout<<r-l+1<<endl;continue;}
            if(num[l]+1==num[r]) {cout<<max(Right[num[l]]-l+1,r-Left[num[r]]+1)<<endl;continue;}
            cout<<max(max(Right[num[l]]-l+1,r-Left[num[r]]+1),RMQ(num[l]+1,num[r]-1))<<endl;
        }
    }

}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章