借助倍增和动态规划可以实现O(1)的时间复杂度的查询

预处理:

①区间DP   转移方程  f[i][j] = min(MAX同理)(f[i][j - 1],f[i + ][j - 1])  f[i][j]表示从i位置开始的后2^j个数中的最大值

用f[i][j]表示从j到j+2^i-1的最小值(长度显然为2^i)。

任意一段的最小值显然等于min(前半段最小值,后半段最小值)。

那么f[i][j]如何用其他状态来继承呢?

j到j+2^i-1的长度为2^i,那么一半的长度就等于2^(i-1)。

那么前半段的状态表示为f[i-1][j]。

后半段的长度也为2^(i-1),起始位置为j+2^(i-1)。

那么后半段的状态表示为f[i-1][j+2^(i-1)]。

②不过区间在增加时,每次并不是增加一个长度,而是基于倍增思想,用二进制右移,每次增加2^i个长度 ,最多增加logn次

这样预处理了所有2的幂次的小区间的最值

关于倍增法链接

查询:

③对于每个区间,分成两段长度为的区间,再取个最值(这里的两个区间是可以有交集的,因为重复区间并不影响最值)

比如3,4,6,5,3一种分成3,4,6和6,5,3,另一种分成3,4,6和5,3,最大值都是6,没影响。

首先明确 2^log(a)>a/2

这个很简单,因为log(a)表示小于等于a的2的最大几次方。比如说log(4)=2,log(5)=2,log(6)=2,log(7)=2,log(8)=3,log(9)=3…….

那么我们要查询x到y的最小值。设len=y-x+1,t=log(len),根据上面的定理:2^t>len/2,从位置上来说,x+2^t越过了x到y的中间!

因为位置过了一半,所以x到y的最小值可以表示为min(从x往后2^t的最小值,从y往前2^t的最小值),前面的状态表示为f[t][x]

设后面(从y往前2^t的最小值)的初始位置是k,那么k+2^t-1=y,所以k=y-2^t+1,所以后面的状态表示为f[t][y-2^t+1]

所以x到y的最小值表示为f(f[t][x],f[t][y-2^t+1]),所以查询时间复杂度是O(1)

④所以O(nlogn)预处理,O(1)查询最值  但不支持修改

预处理时间复杂度O(nlogn),查询时间O(1)。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
using namespace std;
int map[1000005][20];
int N,K;
void work()
{
int i,j;
for(j=1;1<<j<=N;j++)
for(i=1;i+(1<<j)-1<=N;i++)//i+(1<<j)-1<=n是为了保证区间左端点不超出总数n
map[i][j]=min(map[i][j-1],map[i+(1<<j-1)][j-1]);//实质是动态规划
}
int question(int z,int y)
{
int x=int (log(y-z+1)/log(2));//注意y-z要加一才为区间长度
return min(map[z][x],map[y-(1<<x)+1][x]);//分别以左右两个端点为基础,向区间内跳1<<x的最
//大值;
}
int main()
{ scanf("%d",&N);//输入数据总数
scanf("%d",&K);//输入询问次数k
for(int i=1;i<=N;i++)
scanf("%d",&map[i][0]);//数据输入加初始化,即从i开始向右走2的0次方的区间中的最大值,(注//意i到i的长度为一)。
work();//预处理
for(int i=1;i<=K;i++) { int a,b;
scanf("%d%d",&a,&b);
printf("%d ",question(a,b));//输出结果
}
return 0;
}
 

最新文章

  1. zoj3806Incircle and Circumcircle
  2. HDU 1010 Tempter of the Bone
  3. 揣摩实现一个ioc容器需要做的事情
  4. lock模拟CountDownEvent
  5. [BTS] Exception occurred when persisting state to the database
  6. protocol buffer 整数序列化
  7. 分析器错误消息: 未能加载文件或程序集“System.WEB.DataVisualization, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35”或它的某一个依赖项。系统找不到指定的文件。
  8. ajax + php + Controller 控制所有后台函数调用
  9. python运维开发(九)----socket
  10. bug fix: openstack can not run swift for pyeclib and liberasurecode do not match
  11. 记录一次APP的转让流程
  12. eclipse工程的jdk从1.7升到1.8后报错解决办法
  13. Android 自定义AlertDialog的实现
  14. Docker:从引擎和运行框架理解Docker(3)
  15. spring boot 的使用
  16. spring cloud 路由Zuul的高可用
  17. HttpClient(一)-- HelloWorld
  18. COOKIE与SESSION、Django的用户认证、From表单
  19. Python3基础 str find+index 是否存在指定字符串,有则返回第一个索引值
  20. Effective STL 阅读笔记: Item 4 ~ 5: Call empty instead of checking size() against zero.

热门文章

  1. MTK Android Driver :Lcm
  2. linux之进程管理(一)
  3. pyecharts的使用及总结
  4. Redis cluster集群配置教程
  5. 【Java】步入OOP 面向对象
  6. labview 机器视觉
  7. Juli函数
  8. day5 作业
  9. API联调神器PostMan使用详解
  10. [整理]svn常见问题汇总