Node:RMQ問題之ST算法

#include <iostream>
#include <stdio.h>
#include <cmath>

using namespace std;
const int maxn=1000010;
const int N=1010;
int data[N];
int f[maxn][20];
int sz;

/*f[i][j]表示 i...2^j-1的最大值,即從第i個數開始連續2^j個數的最大值
2^len>sz -> len*lg2>lgsz  j在[1,len]之間
*/
void ST(bool isUp)
{
    for(int i=0;i<sz;i++)
        f[i][0]=data[i];

    int maxlen=(int)(log((double)sz)/log(2.0));
    //從小到大劃分,開始比較連續兩個之間的大小關係
    for(int len=1;len<=maxlen;len++)
    {
        //枚舉終點
        for(int from=0;from+(1<<len)-1<sz;from++)
        {
            //由鐘點和後續區間得到起點
            int to=from+(1<<(len-1));
            //記錄大小值
            if(!isUp)
                f[from][len]=min(f[from][len-1],f[to][len-1]);
            else
                f[from][len]=max(f[from][len-1],f[to][len-1]);
            //cout<<"["<<from<<","<<from+(1<<len)-1<<"]"<<": "<<f[from][len]<<"  ";
        }
        cout<<endl;
    }
}

//l...r -> l...l+2^len-1 + r-2^len+1...r-2^len+1-1+2^len -> l...l+2^len-1 + r-2^len+1...r
int RMQ_min(int l,int r)
{
    int len=(int)(log((double)(r-l+1))/log(2.0));
    return min(f[l][len],f[r-(1<<len)+1][len]);
}

int RMQ_max(int l,int r)
{
    int len=(int)(log((double)(r-l+1))/log(2.0));
    return max(f[l][len],f[r-(1<<len)+1][len]);
}
int main()
{
    while(cin>>sz)
    {
        for(int i=0;i<sz;i++)
            cin>>data[i];
        ST(true);
        int l,r;
        while(cin>>l>>r)
        {
            if(l+r==0)
                break;
            cout<<RMQ_max(l,r)<<endl;
        }
    }
	return 0;
}

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