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

题面

【题目描述】
农夫 JohnJohnN(1<=N<=50,000)N(1 <= N <= 50,000)头牛总是按同一序列排队. 有一天,JohnJohn 决定让一些牛们玩一场飞盘比赛. 他准备找一群在队列中位置连续的牛来进行比赛. 但是为了避免水平悬殊,牛的身高不应该相差太大. JohnJohn准备了Q(1<=Q<=180,000)Q (1 <= Q <= 180,000)个可能的牛的选择和所有牛的身高 (1<=1 <=身高<=1,000,000<= 1,000,000). 他想知道每一组里面最高和最低的牛的身高差别.
【输入】
11行:N,QN,Q
22N+1N+1行:每头牛的身高
N+2N+2N+Q+1N+Q+1行:两个整数AABB,表示从AABB的所有牛。(1<=A<=B<=N1<=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[i][j]:表示序列a[i]a[i]开始,连续2j2^j个数的最大值。
s[i][j]s[i][j]:表示序列a[i]a[i]开始,连续2j2^j个数的最小值。
状态转移方程:
f[i][j]=max(f[i][j1],f[i+2j1][j1])f[i][j]=max(f[i][j-1],f[i+2^{j-1}][j-1])
s[i][j]=minx(s[i][j1],s[i+2j1][j1])s[i][j]=minx(s[i][j-1],s[i+2^{j-1}][j-1])

询问区间a[x]a[x] ~ a[y]a[y]最大、小值?
找到一个kk,使得[x,x+2k1][y2k+1,y]=[x,y][x , x+2^k-1 ]∪[ y-2^k+1 , y]=[x,y]
需要满足:2k<=yx+12^k<=y-x+1
k=log2(yx+1)k=log_2(y-x+1)
区间[x,y][x,y]最大值=max(f[x][k],f[y2k1][k])max( f[x][k], f[y-2^k-1][k] )
区间[x,y][x,y]最小值=min(s[x][k],s[y2k1][k])min( s[x][k], s[y-2^k-1][k] )

参考程序

#include<bits/stdc++.h>
#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\n",max(f[x][k],f[y-(1<<k)+1][k])-min(s[x][k],s[y-(1<<k)+1][k]));
    } 
    return 0;
} 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章