线段树 (第一次尝试)

来源:互联网 发布:windows官网 编辑:程序博客网 时间:2024/04/30 17:54

A

Time Limit:10000MS  Memory Limit:65536K
Total Submit:94 Accepted:32

Description

有n(1<=n<=100000)个数a1,a2,a3,…,an-1,an(-100000<=ai<=100000), 对于m次(1<=m<=100000)as到at区间的询问,求该区间的任意两个数差值的最大值。

Input

输入由多组数据组成。每组数据,第1行输入一个数n;第2行输入n个整数,每个数后用空格隔开,分别表示a1,a2,……,an-1,an;第3行输入一个m。第4到m+3行,每行输入两个整数s和t(1<=s<=t<=n),表示要查询的区间为as到at。

Output

对于每个查询输出一行,表示该区间内任意两个数差值的最大值。

Sample Input

510 3 -2 5 -931 52 43 331 3 -531 32 31 2

 

Sample Output

1970882
看到这道题目,像我们这些水手肯定以一般的思路,先建立数组然后然后在要求的数组范围内全部遍历一边,但仔细看看这道题目,这道题目
的限制时间长达10S,时间越多越觉得平常思路不可行,但心里还是不放心,先尝试着普通思路做了一遍,很高兴的TLE,于是,我问了几位了
A了的高手们,一位小牛说m才100000;只要运行m*00就不会超,于是有种方法把100000分位以300个数为一个集体的,在每个集体
中记录最大值和最小值;这样一来,如果要求首位之间的两个数之间绝对值最大的就只要遍历100000/300,所以时间当然OK了,方法也肯巧妙
,时间复杂度也才(m*m/300);但比起线段树的(m*logm)还是慢了很多,但这题的话可能找最大值最小值找了好几次,所以时间也不
见得少了很多;
线段树是在2分分治的基础上的,它的好处一开始先是作预处理,然后在进行更新;然后在统计;
具体怎么样我也还不怎么懂,再去做做这类题巩固巩固!
我的代码如下:
#include<stdio.h>
#define Max(a,b) a > b ? a : b
#define Min(a,b) a > b ? b : a
struct tree
{
 int left;
 int right;
 int mid;
 int max,min;
}seg_tree[500000];
void maketree(int l,int r,int num)
{
 seg_tree[num].left=l;
 seg_tree[num].right=r;
 seg_tree[num].mid=(l+r)/2;
 seg_tree[num].max=-100000;
 seg_tree[num].min=100000;
 if(l+1!=r)
 {
  maketree(l,seg_tree[num].mid,2*num);
  maketree(seg_tree[num].mid,r,2*num+1);
 }
 return ;
}
void insertseg(int i,int value,int num)
{
 if(seg_tree[num].max<value)
  seg_tree[num].max=value;
 if(seg_tree[num].min>value)
     seg_tree[num].min=value;
 if(seg_tree[num].left+1!=seg_tree[num].right)
 {
  if(i<seg_tree[num].mid)
  insertseg(i,value,2*num);
 else insertseg(i,value,2*num+1);
 }
 return ;
}
int findmax(int l,int r,int num)
{
 int x,y;
 if(l==seg_tree[num].left&&r==seg_tree[num].right)
  return seg_tree[num].max;
 if(r<=seg_tree[num].mid)
  return findmax(l,r,num*2);
 if(l>=seg_tree[num].mid)
  return findmax(l,r,num*2+1);
 else
  //return Max(findmax(l,seg_tree[num].mid,num*2),findmax(seg_tree[num].mid,r,num*2+1));
 {
  x = findmax(l,seg_tree[num].mid,num*2);
  y = findmax(seg_tree[num].mid,r,num*2+1);
  return Max(x,y);
 }
}
int findmin(int l,int r,int num)
{
 int x,y;
 if(l==seg_tree[num].left&&r==seg_tree[num].right)
  return seg_tree[num].min;
 if(r<=seg_tree[num].mid)
  return findmin(l,r,num*2);
 if(l>=seg_tree[num].mid)
  return findmin(l,r,num*2+1);
 else
  //return Min(findmin(l,seg_tree[num].mid,num*2),findmin(seg_tree[num].mid,r,num*2+1));
 {
  x = findmin(l,seg_tree[num].mid,num*2);
        y = findmin(seg_tree[num].mid,r,num*2+1);
  return Min(x,y);
 }
}
int main()
{
 int n,i,m;
 int temp,start,end;
 while(scanf("%d",&n)!=EOF)
 {
  maketree(1,n+1,1);
  for(i=1;i<=n;i++)
  {
   scanf("%d",&temp);
   insertseg(i,temp,1);
  }
  scanf("%d",&m);
  while(m--)
  {
   scanf("%d%d",&start,&end);
   printf("%d/n",findmax(start,end+1,1)-findmin(start,end+1,1));
  }
 }
 return 0;
}

 有大牛更好的代码麻烦留下!!谢谢

原创粉丝点击