POJ3264 Balanced Lineup 线段树|ST表

Balanced Lineup
Time Limit: 5000MS Memory Limit: 65536K
Total Submissions: 39453 Accepted: 18511
Case Time Limit: 2000MS

Description

For the daily milking, Farmer John's N cows (1 ≤ N ≤ 50,000) always line up in the same order. One day Farmer John decides to organize a game of Ultimate Frisbee with some of the cows. To keep things simple, he will take a contiguous range of cows from the milking lineup to play the game. However, for all the cows to have fun they should not differ too much in height.

Farmer John has made a list of Q (1 ≤ Q ≤ 200,000) potential groups of cows and their heights (1 ≤ height ≤ 1,000,000). For each group, he wants your help to determine the difference in height between the shortest and the tallest cow in the group.

Input

Line 1: Two space-separated integers,  N and  Q
Lines 2.. N+1: Line  i+1 contains a single integer that is the height of cow  i 
Lines  N+2.. N+ Q+1: Two integers  A and  B (1 ≤  A ≤  B ≤  N), representing the range of cows from  A to  B inclusive.

Output

Lines 1.. Q: Each line contains a single integer that is a response to a reply and indicates the difference in height between the tallest and shortest cow in the range.

Sample Input

6 3
1
7
3
4
2
5
1 5
4 6
2 2

Sample Output

6
3
0
两种解法:
一,
最基础的线段树入门题:没有修改。
线段树知识点①:用全局变量更新结果时,只需要在包含时更新,然后根据区间中点m判断是否向左后向右走

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;

const int maxn=50000+10;
int Max[maxn*4],Min[maxn*4];

void pushUp(int k){
    Max[k]=max(Max[k*2],Max[k*2+1]);
    Min[k]=min(Min[k*2],Min[k*2+1]);
}

void build(int k,int l,int r){
    if(l==r){
        int x;
        scanf("%d",&x);
        Max[k]=Min[k]=x;
        return ;
    }
    int m=(l+r)/2;
    build(k*2,l,m);
    build(k*2+1,m+1,r);
    pushUp(k);
}

int maxv,minv;

void ask(int a,int b,int k,int l,int r){
    if(a<=l && r<=b){
        maxv=max(maxv,Max[k]);minv=min(minv,Min[k]);
        return ;
    }
    int m=(l+r)/2;
    if(a<=m)
        ask(a,b,k*2,l,m);
    if(b>m)
        ask(a,b,k*2+1,m+1,r);
}

int main()
{
    int i,j,res,n,q;
    scanf("%d%d",&n,&q);
    build(1,1,n);
    while(q--){
        int a,b;
        scanf("%d%d",&a,&b);
        if(a>b){
            int t=a;a=b;b=t;
        }
        maxv=-1,minv=1000000+1;
        ask(a,b,1,1,n);
        printf("%d\n",maxv-minv);
    }
    return 0;
}

二、
SparseTable(ST表)
简练地总结ST算法:
f[i,j]表示以i为起点,区间长度为2^j的区间最值,此时区间为[i,i + 2^j - 1]。
②求f[i,j]时,将其分成两等份,即f[i][j-1],f[i+2^(j-1)][j-1],得f[i,j]=min(f[i][j-1],f[i+2^(j-1)][j-1])
初始态为:f[i][0]=a[i];
求f[i][j]时就采用递推,顺序是:先求区间长度为1的,再求长度为2的,再求长度为4的,即:
先求f[0][1],f[1][1],f[2][1],..,f[n][1],再求f[1][2],f[2][2],f[3][2],...,f[m][2]..,之后求f[1][3],f[2][3],...,f[k][3]
③查询时,将查询区间[a,b]分成两个可能重叠但一定能完全覆盖[a,b]的区间,即从a往后找一段,从b往前找一段,这两段的最值即答案。ans=min(f[a,k],f[b-2^k+1][k]),k为区间长度的log
②是预处理:O(nlogn) ③是查询:O(1)

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <algorithm>
using namespace std;

const int maxn=50000+10;
int a[maxn],fax[maxn][21],fin[maxn][21],n;

void Init(){
    int i,j,k;
    for(i=0;i<n;i++)
        fax[i][0]=fin[i][0]=a[i];
    k=int(log(double(n))/log(2.0));
    for(j=1;j<=k;j++)
        for(i=0;i<n;i++)
            if(i+(1<<j)-1<n){
                fax[i][j]=max(fax[i][j-1],fax[i+(1<<(j-1))][j-1]);
                fin[i][j]=min(fin[i][j-1],fin[i+(1<<(j-1))][j-1]);
            }
}

int cal(int l,int r){
    int k=(int)(log((double)(r-l+1))/(log(2.0)));
    int maxv=max(fax[l][k],fax[r-(1<<k)+1][k]);
    int minv=min(fin[l][k],fin[r-(1<<k)+1][k]);
    return maxv-minv;
}

int main()
{
    int x,y,i,q;
    scanf("%d%d",&n,&q);
    for(i=0;i<n;i++)
        scanf("%d",&a[i]);
    Init();
    while(q--){
        scanf("%d%d",&x,&y);
        printf("%d\n",cal(x-1,y-1));
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值