线段树pku3264 [i,j]最大最小数差

 

/*
pku3264
大意是给你一串数字,然后问你从第i个到第j个中最大的数减去最小的数的值
线段树模型是这样的,先初始化一颗线段树,然后边读取数据边做预处理,
把每组读进的数据经过的路径都更新对应节点的最大值和最小值。
比如第4个数据经过的路径就是<1,6>--<3,6>--<3,4>&&<4,6>--<4,5>
OK~ 这个插入复杂度logn. N个数据总共是Nlogn ,没问题,完全可以接受。
*/
#include <iostream>
using namespace std;

#define size 400000
#define inf 2147483647

struct tree
{
       int left;
       int right;
       int max;
       int min;
};
tree xds[size];线段树数组

void init(int left,int right,int step)建树
{
       int left_1=2*step;
       int right_1=2*step+1;
       xds[step].left=left;
       xds[step].right=right;
       xds[step].min=inf;
       xds[step].max=0;
       if(right-left<=1)return;
       init(left,(left+right)/2,left_1);
       init((left+right)/2,right,right_1);
}

int kk=0;

void cr(int n,int step)插入操作
{
       int left=2*step;
       int right=2*step+1;
       if(n>xds[step].max)
              xds[step].max=n;
       if(n<xds[step].min)
              xds[step].min=n;
       if(kk>=xds[left].left&&kk<=xds[left].right)
              cr(n,left);
       if(kk>=xds[right].left&&kk<=xds[right].right)
              cr(n,right);
      return ;
}
tree search(int left,int right,int step)/查询
{
       tree ret;
       int left_1=2*step;
       int right_1=2*step+1;
       if(left==xds[step].left&&right==xds[step].right)
       {
              return xds[step];
       }
       if(left<xds[left_1].right)
       {
              if(right<=xds[left_1].right)
              {
                     ret=search(left,right,left_1);
              }
              else///注意这儿,线段分段查询时的处理要注意
              {
                     tree t1=search(left,xds[left_1].right,left_1);
                     tree t2=search(xds[right_1].left,right,right_1);
                     if(t1.max>t2.max)
                            t2.max=t1.max;
                     if(t1.min<t2.min)
                            t2.min=t1.min;
                     return t2;
              }
       }
       else
       {
              return search(left,right,right_1);
       }
       return ret;
}
int main()
{
       int n,m;
       while(scanf("%d %d",&n,&m)!=EOF)
       {
              init(1,n,1);
              int i;
              int k;
              int k1,k2;
              for(i=1;i<=n;i++)
              {
                     kk=i;
                     scanf("%d",&k);
                     cr(k,1);
              }
              for(i=0;i<m;i++)
              {
                     scanf("%d %d",&k1,&k2);
                     if(k1==k2)
                     {
                            printf("0\n");
                            continue;
                     }
                     tree ret=search(k1,k2,1);
                     printf("%d\n",ret.max-ret.min);
              }
       }
       return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值