线段树 (第一次尝试)
来源:互联网 发布: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 : astruct 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;
}
有大牛更好的代码麻烦留下!!谢谢
- 线段树 (第一次尝试)
- 二叉树第一次尝试
- CONS形式化 (第一次尝试)
- 链表(第一次错误尝试)
- 第一次尝试
- 第一次尝试
- 第一次尝试
- 第一次尝试
- 第一次尝试
- 第一次尝试
- 第一次尝试
- 第一次尝试
- html第一次尝试(百度页面)
- 第一次写的线段树
- ZOJ_1610_第一次写线段树
- SPOJ GSS1 第一次线段树
- poj2352~树状数组~线段树尝试失败~
- 第一次尝试BLOG!
- UML 类图简介
- 浅析HTTP协议
- log4j与log4j.properties的配置说明
- (网站项目篇)网站整合需求分析报告
- hibernate的各种保存方式的区别 (save,persist,update,saveOrUpdte,merge,flush,lock)等
- 线段树 (第一次尝试)
- IBM禁止员工使用Microsoft Office
- 学习
- 解决XP中时间同步时“RPC服务不可用”
- 运行jar应用程序引用其他jar包的四种方法
- 开始我新的一天!!!
- 开始学习了,呵呵
- 收支管理,如何能知道,自己到底还有多少钱呢?
- 可以让你少奋斗十年的工作经验