【題解】「USACO 2007 Jan」Balanced Lineup(ST表)


額面
【タイトル説明】農夫J o h n JohnのN(1)<=N==50,000)N(1<=N==50,000)N(1<=N==50,000)の頭牛はいつも同じ順番で並んでいます.ある日、J oh John Johnはいくつかの牛たちに飛盤競技をさせることにしました.彼は行列の中で連続した牛を探して試合をしますが、水平差がないようにします.牛の身長はそんなに差があるべきではないです.J o h n JohnはQ(1<=Q==180,000)Q(1<==Q==180,000)Q(1==180,000)個の可能な牛の選択とすべての牛の身長(1<=1==身長、=1,000,000、=1,000、<1,000,000、=1,000、=1,000、=1,000、=1,000、=1,000、=1,000の高さ)の高さを入力しています.Q 2番目の2からN+1 N+1行:1頭の牛の身長はN+2 N+2 N+2 N+2からN+Q+1 N+1 N+Q+1行:2つの整数AとB+Bは、AからBまでの牛の全てを表しています.(1<=A<=B==N 1<=A==B<=N 1<=A==B==N)【出力】行ごとの個数を出力し、最大数と最小数の差【サンプル入力】
6 3
1
7
3
4
2
5
1 5
4 6
2 2
【サンプル出力】
6
3
0
アルゴリズム解析
ST表テンプレートのテーマ.a配列はN頭牛の身長を表しています.f[i][j]f[j]f[i]、[j]:シーケンスa[i]a[i]a[i]から始まり、2 j 2^j 2 jまでの最大値を示す.s[i][j]s[i]s[i]s[j]:シーケンスa[i]a[i]a[i]から始まり、2 j 2^j 2 jの個数の最小値を表す.状態移行方程式:f[i][j]=m a x(f[i]、[j−1],f[i+2 j−1]、[j−1]、[j−1]]、[j−1]]f[i]=[j]=[j]=[j]=max=max=f[i]、[j]、f[i+2{j−1]]]、[i]]f[j]、[j]=max=max=max=max=max=max=max=max[f[f[f[i[i[i"""""""[j""""""""=j"=j""=f[j"=[j"=max[j"=[j""=max[j"=max[j"=1)[j−1]s[i]=minx(s[i][j-1],s[i+2^{j-1][j-1]]s[i]=minx(s[i]、[j−1],s[i+2 j−1][j−1]
質問区間a[x]a[x]a[x]~a[y]a[y]a[y]a[y]最大、小値?k k kを見つけて、[x,x+2 k+1]““−1]”[y−2 k+1,y]=[x,y]=[x,x][x,x+2 k-1]_;[y+2 k+1][x+1]===[x+1]““““““““x+1]]]]]]]“““““““““““““x+1]]]]]]]]]]]“““““““““““““““““““““““““““““““““““““““k<=y-x+1 2 k<=y−x+1はk=l o g 2(y−x+1)k=l o g_2(y-x+1)k=log 2(y−−x+1)区間[x,y][x][x]、[x][x,y]最大値=m a x(f[x][k],f[y−2 k−−1]]、[k])max(f[y−2 k])max(f[x]、[k])(f[x]、[k],f[x],f[y−2 k],f[y−2 k],f[y−2 k]、[k],f[y−2 k],f[k],f[y−2 k],f[y−2 k],f[y−2 k],f[k],f[y−2 k],f[k],f[y−2 k],f[x],f[y−2 k],f[y s[x][k],s[y-2 k-1][k]m i n(s[x][k],s[y−2 k−1][k]
参考プログラム
#include
#define N 100010
using namespace std;
int f[N][25],s[N][25];
int n,m,x,y;
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&f[i][0]);
        s[i][0]=f[i][0];		//   
    }
         
    for(int j=1;(1<<j)<=n;j++)
        for(int i=1;i+(1<<j)-1<=n;i++)
        {
            f[i][j]=max(f[i][j-1],f[i+(1<<(j-1))][j-1]);
            s[i][j]=min(s[i][j-1],s[i+(1<<(j-1))][j-1]); 
        }
    while(m--)
    {
        scanf("%d%d",&x,&y);
        int k=log(y-x+1)/log(2);
        printf("%d
"
,max(f[x][k],f[y-(1<<k)+1][k])-min(s[x][k],s[y-(1<<k)+1][k])); } return 0; }