http://poj.org/problem?id=3264

来源:互联网 发布:淘宝饰品店名字 编辑:程序博客网 时间:2024/06/08 17:42

poj   水题一枚。。呵呵,,虽说是水题,但是还是有些地方要注意,我之前就wa好多次。。呵呵。。这题是关于线段树的入门级的水题。但还的仔细看题!

首先:需要注意的是数组大小。咋样一看会发现,数据有点大,但是切不可盲目下结论,以为要开好大的数组,但是切记,在线段树内要求数组大些,但是对于这道题,在输入数据时,int 足够,注意。在线段树内,int可以,但是你定义的N要求扩大,如(m[n<<4]).因为线段树上要求有多重循环,有递归的使用,因此一般比其他的数据要循环的多次,要求的数组大小也要大一些,还有一点就是在进行时要求最大值或最小值进行赋值。因为首先对于这组数据他并没有更新,所以每次查询时都必须从原来的数据中查找,但是每次查找后都会保留这次的最大值与最小值。以至于在进行下一次查询时,如果不把上次的最大值与最小值重新赋值的话,就会影响下次的最大值与最小值,(也许下次的最大值比下次的大,就保持不变,下次的最小值也许比上次的大,这样所求的值也就不会变,但是这样求得结果就会有问题)。。以下

附代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int N=200005;
int minn,maxn;
int root1[N<<4],root2[N<<4];
int a[N];
void make_tree(int l,int r,int rt)
{
    if(l==r)
    {
        root1[rt]=a[r];
        root2[rt]=a[r];
        return ;
    }
    int m=(l+r)>>1;
    make_tree(l,m,rt*2);
    make_tree(m+1,r,rt*2+1);
    root1[rt]=max(root1[rt*2],root1[rt*2+1]);
    root2[rt]=min(root2[rt*2],root2[rt*2+1]);
}
void query(int l,int r,int rt,int x,int y)
{
    if(x<=l&&y>=r)
    {
        maxn=max(maxn,root1[rt]);
        minn=min(minn,root2[rt]);
        return ;
    }
    int m=(l+r)>>1;
    if(x>m)  query(m+1,r,rt*2+1,x,y);
        else if(y<=m)  query(l,m,rt*2,x,y);
    else
    {
        query(l,m,rt*2,x,y);
        query(m+1,r,rt*2+1,x,y);
    }
}
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
    }
    make_tree(1,n,1);
    int x,y;
    for(int i=0;i<m;i++)
    {
        scanf("%d%d",&x,&y);
        maxn=-999,minn=1000001;//注意每次输入一组数据时都要赋初值。否则最大或最小会储存上次的。因此要注意下!!
        query(1,n,1,x,y);
        printf("%d\n",maxn-minn);
    }
    return 0;
}

原创粉丝点击