线段树——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;
}

 

 

 

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