An easy problem A

Time Limit: 1000/1000MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others)

Problem Description

N个数排成一列,Q个询问,每次询问一段区间内的数的极差是多少。

Input

第一行两个整数N(1≤N≤50000),Q(1≤Q≤200000)。接下来一行N个整数a1 a2 a3 ….an,(1≤ai≤1000000000)。接下来Q行,每行两个整数L,R(1≤L≤R≤N)。

Output

对于每个询问输出一行,一个整数表示区间内的极差。

Sample Input

5 3

3 2 7 9 10

1 5

2 3

3 5

Sample Output

8

5

3


解题心得:

一、线段树

1. 这是一个最简单的线段树的模板,主要是入门理解线段树。当数据量比较大,需要多次询问,多次修改维护数据时,就需要使用到线段树的数据结构。线段树的每个节点代表的是一段线段,每次修改这个线段,就可以由此对每个区间进行维护,缩减时间复杂度和空间复杂度。

2. 一般线段树的空间复杂度是O(4n),建立线段树时间复杂度是O(logn),向上更新的时间复杂度是O(logn),询问的时间复杂度是O(logn),如果不使用线段树就遍历硬怼时间复杂度是O(n^2)。线段树是根节点将根节点代表的线段均分为两个线段,分别是左子节点和右子节点,然后一直分下去直到一个线段的长度为1(只有一个数)对该点进行初始赋值,然后向上维护得到每一个线段的需要得到值,线段树就是尽量避免对单个的点进行操作,而是对区间进行维护,这个就避免一个点一个点的去比较,可以直接从区间上面进行操作,树形结构可以很方便的进行维护操作。

3. 就本题来说就是将整个数列按照完美二叉树的样子直接分下去,一直分到区间长度为1,这时这个节点的最大值和最小值都是他自己,然后再向上更新,向上更新的时候父节点的最大值和最小值又他的两个子节点得到,一直向上更新,时间复杂度是nlogn。

二、

  1. 这个还可以使用RMQ算法,即区间最值查询算法,这个算法就是在区间中使用动态规划对这个区间进行预处理,倍增思想。
  2. 动态规划时创建一个dp[i][j],代表以I为起点长度为2^j次方的区间最值,它的转移方程式是dp[I][j] = max(dp[i][j-1],dp[i+2^(j-1)][j-1]),它的意思是从i开始长度为2^j区间的最大值和i+2^(j-1)和长度为2^(j-1)区间的最大值(倍增算法的基础运用)。
  3. 当要求在I到j的最大值的时候可以用i到i + 2 ^ x(i+ 2 ^ x < j ) 和 j - 2 ^ x到j中的最大值。(MAX = max(max(num[i],num[I+2^x]),max(num[j-2^x],num[j]))).
  4. 其实仔细想想,线段数和RMQ的算法是相似的,只是实现的方法不一样,但是思想是一样的(一个二分,一个倍增)。都是将点联系起来用区间来表示。

线段树代码
#include<bits/stdc++.h>
using namespace std;
const int maxn = 5e4+100;
struct node
{
int l,r,Max,Min;
}tree[4*maxn];//经计算生成线段树消耗的空间小于4n
int n,m,num[maxn]; //向上更新
void pushup(int root)
{
tree[root].Max = max(tree[root*2].Max,tree[root*2+1].Max);
tree[root].Min = min(tree[root*2].Min,tree[root*2+1].Min);
} //生成线段树
void build_tree(int l,int r,int root)
{
int mid;
tree[root].l = l;
tree[root].r = r;
if(l == r)
{
tree[root].Min = tree[root].Max = num[l];
return ;
}
mid = (l+r)/2;
build_tree(l,mid,root*2);//左孩子
build_tree(mid+1,r,root*2+1);//右孩子
pushup(root);//在线段树已经建成了之后开始向上更新
} //得到最大值
int queryMax(int l,int r,int root)
{
int mid;
if(tree[root].l == l && tree[root].r == r)
return tree[root].Max;
mid = (tree[root].l + tree[root].r) / 2;
if(r <= mid)
return queryMax(l,r,root*2);
else if(l > mid)
return queryMax(l,r,root*2+1);
else return max(queryMax(l,mid,root*2),queryMax(mid+1,r,root*2+1));
} //得到最小值
int queryMin(int l,int r,int root)
{
int mid;
if(tree[root].l == l && tree[root].r == r)
return tree[root].Min;
mid = (tree[root].l + tree[root].r) / 2;
if(r <= mid)
return queryMin(l,r,root*2);
else if(l > mid)
return queryMin(l,r,root*2+1);
else return min(queryMin(l,mid,root*2),queryMin(mid+1,r,root*2+1));
} int main()
{
while(scanf("%d%d",&n,&m) != EOF)
{
for(int i=1;i<=n;i++)
scanf("%d",&num[i]);
build_tree(1,n,1);
while(m--)
{
int a,b;
scanf("%d%d",&a,&b);
`
printf("%d\n",queryMax(a,b,1)-queryMin(a,b,1));
}
}
}

RMQ算法

#include<bits/stdc++.h>
using namespace std;
const int maxn = 5e4+100;
int num[maxn];
int n,m; struct Dp
{
int Min;
int Max;
} dp[maxn][20]; void DP()
{
for(int j=0; j<20; j++)
{
for(int i=1; i<=n; i++)
{
if(j == 0)
{
dp[i][j].Max = dp[i][j].Min = num[i];//当就只有一个数的时候最大值和最小值都是这个数
continue;
}
if(i + (1<<(j - 1)) > n)//不能超出限制
continue;
int k = 1<<(j-1);
dp[i][j].Max = max(dp[i][j-1].Max,dp[i+k][j-1].Max);//状态转移方程式
dp[i][j].Min = min(dp[i][j-1].Min,dp[i+k][j-1].Min);
}
}
}
int main()
{
while(scanf("%d%d",&n,&m) != EOF)
{
memset(dp,0,sizeof(dp)); for(int i=1; i<=n; i++)
scanf("%d",&num[i]);
DP();
while(m--)
{
int l,r,l1,r1;
scanf("%d%d",&l,&r);
//这是将要求的区间化成两重合的可以用dp[i][j]的区间来表示,求最大值
r1 = log2(r-l+1);
l1 = r - (1<<r1) + 1;
printf("%d\n",max(dp[l][r1].Max,dp[l1][r1].Max)-min(dp[l][r1].Min,dp[l1][r1].Min));
}
}
return 0;
}

线段树:CDOJ1591-An easy problem A (RMQ算法和最简单的线段树模板)的更多相关文章

  1. 线段树:CDOJ1592-An easy problem B (线段树的区间合并)

    An easy problem B Time Limit: 2000/1000MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others) Pr ...

  2. 线段树:CDOJ1597-An easy problem C(区间更新的线段树)

    An easy problem C Time Limit: 4000/2000MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others) Pr ...

  3. nyoj 119士兵杀敌(三)(线段树区间最值查询,RMQ算法)

    题目119 题目信息 执行结果 本题排行 讨论区 士兵杀敌(三) 时间限制:2000 ms  |  内存限制:65535 KB 难度:5 描写叙述 南将军统率着N个士兵,士兵分别编号为1~N,南将军常 ...

  4. hdu 5475 An easy problem(暴力 || 线段树区间单点更新)

    http://acm.hdu.edu.cn/showproblem.php?pid=5475 An easy problem Time Limit: 8000/5000 MS (Java/Others ...

  5. HDU 5475 An easy problem 线段树

    An easy problem Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pi ...

  6. UESTC 1591 An easy problem A【线段树点更新裸题】

    An easy problem A Time Limit: 2000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others ...

  7. HDU 5475:An easy problem 这题也能用线段树做???

    An easy problem Time Limit: 8000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) ...

  8. hud-5475 An easy problem(线段树)

    http://acm.hdu.edu.cn/showproblem.php?pid=5475 An easy problem Time Limit: 8000/5000 MS (Java/Others ...

  9. HDU 5475An easy problem 离线set/线段树

    An easy problem Time Limit: 8000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) ...

随机推荐

  1. Linux上常用命令整理(一)—— cat

    近几个月刚从windows上转过来,开始慢慢熟悉linux,先不撕比到底哪个更好,首先要怀着相互借鉴的精神去了解各个平台. Linux上做开发,除去使用文本编辑器做开发的大神之外,大家(包括我这种菜鸟 ...

  2. 057 Insert Interval 插入区间

    给出一个无重叠的按照区间起始端点排序的区间列表.在列表中插入一个新的区间,你要确保列表中的区间仍然有序且不重叠(如果有必要的话,可以合并区间).示例 1:给定区间 [1,3],[6,9],插入并合并 ...

  3. RL_RTX函数

    1 延时:os_itv_set(usFrequency) //设置延时周期,配合os_itv_wait使用:os_itv_wait() 是绝对延迟是包含调用前的时间, os_dly_wait() 是相 ...

  4. 打war包时无法把src/main/java里的xml文件打包上去

    maven打包默认打src/mian/resource里面的xml,而不会去src/main/java,所以 再pom.xml里的bulid节点里加上 <resources> <re ...

  5. [luogu 2634]聪聪可可

    题目描述 聪聪和可可是兄弟俩,他们俩经常为了一些琐事打起来,例如家中只剩下最后一根冰棍而两人都想吃.两个人都想玩儿电脑(可是他们家只有一台电脑)……遇到这种问题,一般情况下石头剪刀布就好了,可是他们已 ...

  6. Linux环境 Java内存快速查看

    最近生产环境遇到内存老是占用很大的情况,16G的内存Free的内存只剩100多M,仿佛一颗定时炸弹一般,说不定就服务Down了.于是开始网上不断的找查看内存使用的方法.现学现卖,以下通过一个例子来演示 ...

  7. SpringBoot 2.x (13):整合ActiveMQ

    ActiveMQ5.x不多做介绍了,主要是SpringBoot的整合 特点: 1)支持来自Java,C,C ++,C#,Ruby,Perl,Python,PHP的各种跨语言客户端和协议 2)支持许多高 ...

  8. 实例练习——轮播图 & 全选/全不选

    1 实例1:轮播图 1)实质就是改变图片的src 2)把图片的路径用数组存起来 3) “下一张”的实现就是改变数组的下标,用一个变量i控制,每次点击下标加1.“上一张”的实现正好相反.注意“i的变化” ...

  9. JFinal免费公开课更新中

    价值千元的课程,免费报名学习,JFinal学院-小木 录制JFinal视频教程,JFinal核心已经周边涉及到微信小程序开发.数据库.前端实战等.

  10. django之分页插件

    from django.utils.safestring import mark_safe class Page: def __init__(self, current_page, data_coun ...