POJ3264
这道题的大体意思就是给你一个数组,然后给定一个区间,求出这个区间的最大值与最小值的差,第一输入的数是数组的长度,第二个数是测试案例的个数,然后接下来就是输入数组的长度。
#include<stdio.h>
#include<string.h>
const int n=50005;
int max(int a,int b){
return a>b?a:b;
}
int min(int a,int b){
return a<b?a:b;
}
int rmax[n<<2];
int lmin[n<<2];
int a[n];
void build(int root,int l,int r)
{
if(r==l)
{
rmax[root]=lmin[root]=a[l];
return;
}
int mid=(l+r)>>1;
build(root<<1,l,mid);
build(root<<1|1,mid+1,r);
rmax[root]=max(rmax[root<<1],rmax[root<<1|1]);
lmin[root]=min(lmin[root<<1],lmin[root<<1|1]);
}
int querymax(int root,int L,int R,int l,int r){
if(l<=L&&r>=R){
return rmax[root];
}
int mid=(L+R)>>1;
int ma=0;
if(l<=mid)
{
ma=max(ma,querymax(root<<1,L,mid,l,r));
}
if(mid<r)
{
ma=max(ma,querymax(root<<1|1,mid+1,R,l,r));
}
return ma;
}
int querymin(int root,int L,int R,int l,int r){
if(l<=L&&r>=R){
return lmin[root];
}
int mid=(L+R)>>1;
int mi=100000002;
if(l<=mid)
{
mi=min(mi,querymin(root<<1,L,mid,l,r));
}
if(mid<r)
{
mi=min(mi,querymin(root<<1|1,mid+1,R,l,r));
}
return mi;
}
int main(){
memset(lmin,1000002,sizeof(lmin));
int x,m,l,r,i;
scanf("%d%d",&x,&m);
for(i=1;i<=x;i++)
scanf("%d",&a[i]);
build(1,1,x);
while(m--)
{
scanf("%d%d",&l,&r);
printf("%d\n",querymax(1,1,x,l,r)-querymin(1,1,x,l,r));
}
return 0;
}
这道题是我做的第一道线段树的题目,应该是POJ上最简单的一道线段树题目了 这道题是先输入两个数,一个是数组的长度,另一个是几个测试案例的数目,然后输入数组 去一个区间内的最大数和最小数之差 我觉得刚开始的拿到这道题目时,我感觉就是拿着线段树的模板往里套 我的想法是需要用到两个数组,分别来存储一个根节点的左右子树的最大值和最小值 建树的时候就开始更新左右节点的最大值和最小值 然后搜索一个区间内的最大值和最小值的时候,用一个max或者min来记录一下,然后不断的去比较,更新max和min值, 在更新max和min的值得时候,有可能查询的区间不在同一个子树上,需要分开查询,然后比较、 最后把这个值返回,然后相减 这个题目综合来说没有什么很难理解的地方,没有涉及到维护和动态更新线段树的值,只有在刚开始建树的时候有更新 |
POJ3264
最新推荐文章于 2019-01-08 02:54:15 发布