線段樹——SDUT3302效率至上

效率至上

 

題意:

題意很簡單,給出一個數目爲n的非有序序列,然後有m次查詢.對於每次查詢輸入兩個正整數l,r請輸出區間[l,r]的最大值與最小值的差值

輸入:

第一行:輸入兩個正整數n,m    (1<=n<=50000,  1<=m<=200000  );

第二行:輸入n個整數  大小範圍爲[1,100000];

接下來的m行,每次兩個正整數l,r (1<=l<=r<=n);

 

輸出:

 輸出區間[l,r]最大值與最小值的差值.

 

思路:

套用線段樹模板,在線段樹結構體里加兩個值,分別記錄當前區間內的最小值和最大值,然後只需要每次選出區間內的最大值和最小值,將他們做減法輸出即可。

 

代碼

#include<iostream>
#include<cstdio>
using namespace std;
struct node
{
    long long l,r,v,ma,mi;
} tree[400000];
long long x,y,MAX,MIN;
int maxn(int a,int b)
{
    return a>b?a:b;
}
int minn(int a,int b)
{
    return a<b?a:b;
}
void build(long long i,long long l,long long r)
{
    tree[i].l=l;
    tree[i].r=r;
    tree[i].v=0;
    tree[i].mi=0x3f3f3f;
    if(l==r)
    {
        scanf("%lld",&tree[i].v);
        tree[i].mi=tree[i].ma=tree[i].v;
        return ;
    }
    long long mid=(l+r)/2;
    build(i*2,l,mid);
    build(i*2+1,mid+1,r);
    tree[i].v=tree[i*2+1].v+tree[i*2].v;
    tree[i].ma=maxn(tree[i*2+1].ma,tree[i*2].ma);
    tree[i].mi=minn(tree[i*2+1].mi,tree[i*2].mi);
}
void maxx(long long i)
{

    if(tree[i].l>=x&&tree[i].r<=y)
    {
            MAX=maxn(MAX,tree[i].ma);
            return ;
    }
    long long mid=(tree[i].l+tree[i].r)/2;
    if(x<=mid)
    {
        maxx(i*2);
    }
    if(y>mid)
    {
        maxx(i*2+1);
    }

}
void minx(long long i)
{
    if(tree[i].l>=x&&tree[i].r<=y)
    {
        MIN=minn(MIN,tree[i].mi);
        return ;
    }
    long long mid=(tree[i].l+tree[i].r)/2;
    if(x<=mid)
    {
        minx(i*2);
    }
    if(y>mid)
    {
        minx(i*2+1);
    }
}
int main()
{
    int n,m,i;
    cin>>n>>m;
    build(1,1,n);
    while(m--)
    {
        MAX=-1;
        MIN=0x3f3f3f;
        scanf("%lld%lld",&x,&y);
        maxx(1);
        minx(1);
        printf("%d\n",MAX-MIN);
    }
    return 0;
}

 

 

 

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