hiho_1070_RMQ
题目
区间最小值查询,但是支持对数组中的任意数字进行修改。
分析
采用RMQ_ST算法的O(1)算法不支持修改,因为每次修改都要重新设置动归数组。因此采用线段树解决,修改和查询的复杂度均为O(logN).
在实现的时候所犯的错误:每次更新一个数字的时候,走到线段树的某个节点,则直接 判断线段树的当前节点代表区间的最小值cur_min是否小于value, 如果大于则更新为value.这样做没有考虑到,当前所要更改的位置就是当前节点区间内最小值的位置,这样cur_min就无效了。
因此,还是需要从上到下找到线段树的叶子节点进行更新,之后递归返回的时候,利用子节点的min来更新父节点的min。
逻辑一定要严密!!!
实现
#include<iostream>
#include<string.h>
#include<iostream>
#include<queue>
#include<cmath>
#include<unordered_map>
#include<unordered_set>
#include<string>
#include<vector>
using namespace std;
const int inf = 1 << 29;
const int kMax = 10005;
struct Node{
int beg;
int end;
int min;
Node(){
min = inf;
}
};
Node gNodes[4 * kMax];
int weight[kMax];
void BuildTree(int node, int beg, int end){
gNodes[node].beg = beg;
gNodes[node].end = end;
if (beg == end){
gNodes[node].min = weight[beg];
return;
}
int left = 2 * node + 1, right = 2 * node + 2;
int mid = (beg + end) / 2;
BuildTree(left, beg, mid);
BuildTree(right, mid + 1, end);
//更新完子节点之后,再更新父节点
gNodes[node].min = gNodes[left].min < gNodes[right].min ? gNodes[left].min : gNodes[right].min;
} void Update(int node, int id, int value){
if (id < gNodes[node].beg || id > gNodes[node].end)
return; if (id == gNodes[node].beg && id == gNodes[node].end){
gNodes[node].min = value;
return;
}
int left = 2 * node + 1, right = 2 * node + 2;
int mid = (gNodes[node].beg + gNodes[node].end) / 2;
if (mid >= id){
Update(left, id, value);
}
else{
Update(right, id, value);
}
//更新完子节点之后,再更新父节点
gNodes[node].min = gNodes[left].min < gNodes[right].min ? gNodes[left].min : gNodes[right].min;
}
int Query(int node, int beg, int end){
if (gNodes[node].beg == beg && gNodes[node].end == end){
return gNodes[node].min;
}
int left = 2 * node + 1, right = 2 * node + 2;
int mid = (gNodes[node].beg + gNodes[node].end) / 2;
if (mid >= end){
return Query(left, beg, end);
}
else if (mid < beg){
return Query(right, beg, end);
}
else{
int left_min = Query(left, beg, mid);
int right_min = Query(right, mid + 1, end);
return left_min < right_min ? left_min : right_min;
}
}
int main(){
int n;
scanf("%d", &n);
for (int i = 0; i < n; i++){
scanf("%d", &weight[i]);
}
BuildTree(0, 0, n - 1);
scanf("%d", &n);
int cmd, beg, end;
for (int i = 0; i < n; i++){
scanf("%d %d %d", &cmd, &beg, &end);
if (cmd == 0){
int result = Query(0, beg-1, end-1);
printf("%d\n", result);
}
else{
Update(0, beg-1, end);
}
}
return 0;
}
hiho_1070_RMQ的更多相关文章
随机推荐
- Java学习之路(七)
1:什么是异常? 中断了正常指令流的事件. 异常是一个对象 ,在出现异常时,虚拟机会生成一个异常对象 生成对象的类是由 JDK 提供的
- texconv下载以及使用命令
包含texconv.exe,测试图片和测试批处理文件 命令: texconv.exe -ft DDS .\src\*.bmp -o .\output\ 下载: http://files.cnblogs ...
- 修改Windows下的键盘映射
在知乎上看见有人说Ctrl键放在A的旁边会更方便,于是我就琢磨着把Cap Lock键改成Ctrl 我肯定不愿意用第三方工具修改的,于是找到了这篇文章,很容易的就修改成功,现在用起来果然舒服多了. 附上 ...
- 0. WP8.1学习笔记
应用程序生命周期: 运行: 在程序NotRunning状态下点击图标,应用将处于Running状态,这会触发一个Actived事件 挂起: 在程序Running状态下, 点击返回键或win键会触发一个 ...
- Java中通过JDBC远程连接Oracle数据库
通过jdbc连接数据库,拢共分三步: 第一步:下载一个JDBC的驱动,然后把jar包扔到项目里并add to build path: 第二步:去本地oracle文件夹下找到“TNSNAMES.ORA” ...
- MySQL日期时间函数大全
DAYOFWEEK(date) 返回日期date是星期几(=星期六,ODBC标准) mysql> select DAYOFWEEK('1998-02-03'); WEEKDAY(date) 返回 ...
- 浅谈Apache性能调优
做了很多WEB系统性能测试,都知道了解测试环境,服务器硬件配置,web服务器参数配置是我们开始测试前首先要做的事情. 针对并发数量来说,不同数量级的用户并发,需求的服务器和web服务参数肯定是不同的. ...
- sql 第 10条 到20条
sql 第 10条 到20条 select * from( select *,ROW_NUMBER () over (order by @@servername) as rownum from tb_ ...
- Cheatsheet: 2013 08.14 ~ 08.19
.NET Lucene.Net ultra fast search for MVC or WebForms site => made easy! C# State Machines HttpCl ...
- SQL多条件查询安全高效比较
ALTER PROCEDURE _tmp @ID VARCHAR(50), @PN VARCHAR(50), @Type INT AS BEGIN /************************* ...