题目

区间最小值查询,但是支持对数组中的任意数字进行修改。

分析

采用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的更多相关文章

随机推荐

  1. Hadoop Mac OSX 安装笔记

    本次测试安装的机器为Mac Book Pro, 系统为 OS X 10.9.4.Hadoop版本2.4.1. 使用Java版本为Oracle的JDK 1.6.0_65. 1. 下载安装 Hadoop2 ...

  2. Radar之获取排列的UITexture数组

    1.定义UITexture二维数组 public UITexture[,] m_UITexture; 2.在 void start() 中分配内存 m_UITexture = , ]; 3.遍历排列的 ...

  3. main函数参数解析

    int argc,char *argv agrc表示参数的个数 argv储存参数 这个函数的意思是逐一输出参数 实际上,main函数也可以带参数.带参数main函数的定义格式如下:void main( ...

  4. js的Prototype属性 解释及常用方法

    函数:原型 每一个构造函数都有一个属性叫做原型(prototype,下面都不再翻译,使用其原文).这个属性非常有用:为一个特定类声明通用的变量或者函数. prototype的定义 你不需要显式地声明一 ...

  5. Struts2的标签库(一)——使用Struts2的标签库

    Struts2的标签库(一) --使用Struts2的标签库 1.Struts2的标签库其实就是一个自定义的标签库,所以它也有它的标签处理类和标签库定义文件: 2.和所有自定义标签一样,我们可以找到S ...

  6. 从exchange2010上面删除特定主题或特定时间的邮件

    昨天在上班的公交上接到同事电话,说他的的部门老大发错了一封邮件到另外一个同事邮箱了,问我能不 能去那个同事的邮箱里面删除,我一想,之前在网上看到过资料,到了公司趁那个误接收邮件的同事还没有来,在服务器 ...

  7. Dev

    调用DoValidate()始终返回true 解决方案 txtCarNo.IsModified = true; result = result & txtCarNo.DoValidate(); ...

  8. VPython—旋转坐标系

    使用arrow( )创建三个坐标轴代表一个坐标系,其中X0-Y0-Z0为参考坐标系(固定不动),X-Y-Z为运动坐标系,这两个坐标系原点重合,运动坐标系可以绕参考坐标系或其自身旋转.在屏幕上输出一个转 ...

  9. [HDOJ5791]Two(DP)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5791 题意:给两个数列,求有多少个公共子序列. dp(i,j)表示a1~ai和b1~bj的公共子序列个 ...

  10. 反弹SHELL汇总

    http://pentestmonkey.net/cheat-sheet/shells/reverse-shell-cheat-sheet Reverse Shell Cheat Sheet If y ...