POJ 3264Balanced Lineup(线段树)

来源:互联网 发布:零售行业数据分析 编辑:程序博客网 时间:2024/06/02 18:38

线段树第一题

输入n和m共有n个数,m个操作

在m个操作中输入a和b在a和b的范围中求出最大值减最小值的和

线段树区间更新问题,将num数组的数先放入到线段树里面的叶子节点,也就是说最底下一层从左到右按顺序就是num[i]的值

在build方法过程中从叶子节点开始向上更新,每两个节点取一个最大和最小

层层更新上去到了树根的时候就是第1个到第n个数的最大值和最小值

如果要具体查询a到b,其实就是查询线段为a到b的最大值减最小值

代码中根据习惯用到了位运算

i<<1就是2*i也就是左孩子序号

 i<<1就是2*i+1也就是右孩子序号

i>>1就是i/2其中

mid就是l和r的中点

上代码:

#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>#include<cmath>#define N 50005using namespace std;struct node {    int l, r, maxn, minn;}tree[N<<2];int max1,min1;int num[N];void build(int l,int r,int i){    tree[i].l=l;    tree[i].r=r;    if(l==r)    {        tree[i].maxn=tree[i].minn=num[l];        return ;    }    int mid=(l+r)>>1;    build(l,mid,i<<1);    build(mid+1,r,i<<1|1);    tree[i].maxn=max(tree[i<<1].maxn,tree[i<<1|1].maxn);    tree[i].minn=min(tree[i<<1].minn,tree[i<<1|1].minn);}void query(int l,int r,int i){    if(l<=tree[i].l&&r>=tree[i].r)    {        min1=min(tree[i].minn,min1);        max1=max(tree[i].maxn,max1);        return ;    }    int mid=(tree[i].l+tree[i].r)>>1;    if(mid<l)query(l,r,i<<1|1);    else if(mid>=r)query(l,r,i<<1);    else {        query(l,r,i<<1);        query(l,r,i<<1|1);    }}int main(){    int n,m;    int a,b;    scanf("%d%d",&n,&m);    for(int i=1;i<=n;i++)        scanf("%d",&num[i]);    build(1,n,1);    for(int i=1;i<=m;i++)    {        scanf("%d%d",&a,&b);        min1=99999999;        max1=-99999999;        query(a,b,1);        printf("%d\n",max1-min1);    }    return 0;}



0 0
原创粉丝点击