poj 3264 Balanced Lineup(st/线段树)

题目大意

查询一个区间输出最大值间最小值的差

用线段树写需要剪枝...本来明明是一道快乐的水题..却t了就用st写了..

线段树

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<set>
#include<stack>

const int maxn=3e5+5;

using namespace std;

int n,m;

struct node{
    int maxn,minn;
} tree[maxn*4];
int arr[maxn],ans1,ans2;

void built(int l,int r,int now)
{
    int mid=(l+r)/2;
    if(l==r)
    {
        tree[now]=(node){arr[l],arr[l]};
        return ;
    }
    built(l,mid,now*2);
    built(mid+1,r,now*2+1);
    tree[now].maxn=max(tree[now*2].maxn,tree[now*2+1].maxn);
    tree[now].minn=min(tree[now*2].minn,tree[now*2+1].minn);
}

void query(int l,int r,int left,int right,int now)
{
    if(ans1>=tree[now].maxn&&ans2<=tree[now].minn) return ;//剪枝
    int mid=(l+r)/2;
    if(l>right) return ;
    if(r<left) return ;
    if(left<=l&&r<=right)
    {
        ans1=max(ans1,tree[now].maxn);
        ans2=min(ans2,tree[now].minn);
    }
    if(l==r) return ;
    query(l,mid,left,right,now*2);
    query(mid+1,r,left,right,now*2+1);
}

int main(){
    
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",arr+i);
    }
    built(1,n,1);
//    for(int i=1;i<=24;i++)
//    {
//        cout<<tree[i].maxn<<endl;
//    }
    for(int i=1;i<=m;i++)
    {
        int l,r;
        scanf("%d%d",&l,&r);
        ans1=0,ans2=0x7fffffff;
        query(1,n,l,r,1);
        //cout<<ans1<<" "<<ans2<<endl;
        printf("%d
",ans1-ans2);
    }
    return 0;
}

st表

#include<cstdio>
#include<cmath>
#include<iostream>

using namespace std;

int a[100005],maxn[100005][35],minn[100005][35],n,m;

void f(){
    int k=log(n)/log(2)+1;
    for(int j=1;j<=k;j++)
    {
        for(int i=1;i<=n;i++)
        {
            if( i + (1 << j) - 1 <= n)

                maxn[i][j]=max(maxn[i][j-1],maxn[i+(1<<(j-1))][j-1]);
                minn[i][j]=min(minn[i][j-1],minn[i+(1<<(j-1))][j-1]);
        }
    }
}

int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        maxn[i][0]=a[i];
        minn[i][0]=a[i];
    }
    f();
    while(m--)
    {
        int l,r;
        scanf("%d%d",&l,&r);
        int k=log(r-l+1)/log(2);
        //cout<<k<<endl;
        printf("%d
",max(maxn[l][k],maxn[r-(1<<k)+1][k])-min(minn[l][k],minn[r-(1<<k)+1][k]));
    }
    return 0;
}
原文地址:https://www.cnblogs.com/minun/p/10473772.html