题目描述

老管家是一个聪明能干的人。他为财主工作了整整10年,财主为了让自已账目更加清楚。要求管家每天记k次账,由于管家聪明能干,因而管家总是让财主十分满意。但是由于一些人的挑拨,财主还是对管家产生了怀疑。于是他决定用一种特别的方法来判断管家的忠诚,他把每次的账目按1,2,3…编号,然后不定时的问管家问题,问题是这样的:在a到b号账中最少的一笔是多少?为了让管家没时间作假他总是一次问多个问题。

分析

关于线段树的详细讲解可以参考拙作(点击传送门):【算法微解读】浅谈线段树
那么我们就开始讲解一下这一道模板题,题目的主要意思就是区间查询最小值。
首先定义线段树的节点的状态segment_tree_node

struct segment_tree_node{//线段树节点状态int Min;//表示当前区间的最小值
}tree[maxn];

接下来就是建树build的过程了。

void build(int l,int r,int nod) {//建树if (l==r) {//如果l与r指针相撞,那么就是已经到了目标区间,赋值tree[nod].Min=a[l];return;}int mid=(l+r)>>1;//取中间midbuild(l,mid,lson); build(mid+1,r,rson);//lson和rson可以恒定义一下,缩短代码pushup(nod);//更新父节点
}

建树好之后,我们要进行一下区间查询的操作,区间查询的本质其实就是将原区间分成两部分,然后对每一个区间的目标区间进行查询。
|----l----|----r----|当做是原区间

  • 情况一:[ll,rr]区间在l区间内,那么就是query(l,mid,ll,rr,lson)意思就是在[l,mid]区间内查询[ll,rr]
  • 情况二:[ll,rr]区间在r区间内,那么就是query(mid+1,r,ll,rr,lson)意思就是在[mid+1,r]区间内查询[ll,rr]
  • 情况三:[ll,rr]区间一部分在l区间内,一部分在r区间内,那么就要把原区间和目标区间都分成两部分,因为线段树中同一深度的区间互不干扰,那么我们就查询query(l,mid,ll,mid,lson),query(mid+1,r,mid+1,rr,rson)

    注:区间查询一般是不需要pushup的,但是如果之前是有区间修改,那么是要pushdown的。
    那么我们通过代码来详细的看一下区间查询最小值是如何写的。

int query(int l,int r,int ll,int rr,int nod) {//区间查询最小值if (l==ll&&r==rr) return tree[nod].Min;//已经找到了目标区间int mid=(l+r)>>1;//取中间if (rr<=mid) return query(l,mid,ll,rr,lson);//整个区间在mid的左边else if (ll>mid) return query(mid+1,r,ll,rr,rson);//整个区间在mid的右边else return min(query(l,mid,ll,mid,lson),query(mid+1,r,mid+1,rr,rson));//区间被mid分成两部分
}

主程序就不写了,也是很简单的

恒定义:define lson nod<<1 define rson (nod<<1)+1

完整代码

#include <bits/stdc++.h>
#define lson nod<<1
#define rson (nod<<1)+1
#define ms(a,b) memset(a,b,sizeof(a))
using namespace std;
const int maxn=100000<<2;
const int inf=1<<30;
struct segment_tree_node{//线段树节点状态int Min;
}tree[maxn];
int n,m;
int a[maxn>>2];
inline int read() {int x=0,w=0; char ch=0;while (!isdigit(ch)) {w|=ch=='-';ch=getchar();}while (isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}return w?-x:x;
}
void pushup(int nod) {//pushup操作,更新父节点内的信息tree[nod].Min=min(tree[lson].Min,tree[rson].Min);
}
void build(int l,int r,int nod) {//建树if (l==r) {//如果l与r指针相撞,那么就是已经到了目标区间,赋值tree[nod].Min=a[l];return;}int mid=(l+r)>>1;//取中间midbuild(l,mid,lson); build(mid+1,r,rson);//lson和rson可以恒定义一下,缩短代码pushup(nod);//更新父节点
}
int query(int l,int r,int ll,int rr,int nod) {//区间查询最小值if (l==ll&&r==rr) return tree[nod].Min;//已经找到了目标区间int mid=(l+r)>>1;//取中间if (rr<=mid) return query(l,mid,ll,rr,lson);//整个区间在mid的左边else if (ll>mid) return query(mid+1,r,ll,rr,rson);//整个区间在mid的右边else return min(query(l,mid,ll,mid,lson),query(mid+1,r,mid+1,rr,rson));//区间被mid分成两部分
}
int main() {ms(tree,inf);//先将树的每一个节点都赋值成inf,因为我们要求最小值n=read(),m=read();for (int i=1;i<=n;i++) a[i]=read();build(1,n,1);while (m--) {int x=read(),y=read();printf("%d ",query(1,n,x,y,1));}return 0;
}

转载于:https://www.cnblogs.com/Dawn-Star/p/9782076.html

【洛谷P1816 忠诚】线段树相关推荐

  1. 洛谷P1816 忠诚 题解

    洛谷P1816 忠诚 题解 题目描述 老管家是一个聪明能干的人.他为财主工作了整整10年,财主为了让自已账目更加清楚.要求管家每天记k次账,由于管家聪明能干,因而管家总是让财主十分满意.但是由于一些人 ...

  2. 洛谷 P1816 忠诚

    题目描述 老管家是一个聪明能干的人.他为财主工作了整整10年,财主为了让自已账目更加清楚.要求管家每天记k次账,由于管家聪明能干,因而管家总是让财主十分满意.但是由于一些人的挑拨,财主还是对管家产生了 ...

  3. 洛谷 P1816 忠诚题解

    题目描述 老管家是一个聪明能干的人.他为财主工作了整整10年,财主为了让自已账目更加清楚.要求管家每天记k次账,由于管家聪明能干,因而管家总是让财主十分满意.但是由于一些人的挑拨,财主还是对管家产生了 ...

  4. 洛谷 p3372 模板-线段树 1

    题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数加上x 2.求出某区间每一个数的和 输入输出格式 输入格式: 第一行包含两个整数N.M,分别表示该数列数字的个数和操作的总个 ...

  5. 洛谷 - P1198 - 最大数 - 线段树

    https://www.luogu.org/problemnew/show/P1198 要问区间最大值,肯定是要用线段树的,不能用树状数组.(因为没有逆元?但是题目求的是最后一段,可以改成类似前缀和啊 ...

  6. 【洛谷 3372】线段树 1

    题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数加上x 2.求出某区间每一个数的和 输入格式 第一行包含两个整数N.M,分别表示该数列数字的个数和操作的总个数. 第二行包含 ...

  7. 洛谷P3352 [ZJOI2016]线段树

    P3352 [ZJOI2016]线段树 (^ w ^) 题目描述 小Yuuka遇到了一个题目:有一个序列a_1,a_2,?,a_n,q次操作,每次把一个区间内的数改成区间内的最大值,问最后每个数是多少 ...

  8. 【洛谷】【线段树】P3353 在你窗外闪耀的星星

    [题目描述:] /* 飞逝的的时光不会模糊我对你的记忆.难以相信从我第一次见到你以来已经过去了3年.我仍然还生动地记得,3年前,在美丽的集美中学,从我看到你微笑着走出教室,你将头向后仰,柔和的晚霞照耀 ...

  9. 洛谷 P1816 忠诚 ST函数

    题目描述 老管家是一个聪明能干的人.他为财主工作了整整10年,财主为了让自已账目更加清楚.要求管家每天记k次账,由于管家聪明能干,因而管家总是让财主十分满意.但是由于一些人的挑拨,财主还是对管家产生了 ...

最新文章

  1. 数据结构-浙大 MOOC 笔记一 基本概念
  2. python快速编程入门教程-终于懂得python快速编程入门教程
  3. java关于throw Exception的一个小秘密
  4. mysql 日志记录 archive_完美起航-Mysql日志管理、备份与恢复
  5. 算法设计与分析——动态规划——最长公共子序列
  6. 7-5 汽车加油问题 (20 分)(思路+详解)Come 宝!!!!!!!!!!!!!
  7. C/C++获取指定网口的IP地址
  8. 年轻人有梦想,老人有回忆
  9. gdb打印STL和boost容器
  10. 无法安装Windows Live“OnCatalogResult:0x80190194”错误的解决方法
  11. 安装adt-bundle-windows-x86-20130917时遇到的问题及解决方法
  12. Linux中配置pacman镜像源(manjaro)
  13. 基于springboot+vue的旅游信息(旅游线路)网站(前后端分离)
  14. 批量修改密码脚本--------小练习
  15. VMware安装国产化操作系统--统信UOS
  16. 平面设计学习需要会哪些知识
  17. STC89C51单片机
  18. 二分查找例题(二)洛谷P1163
  19. 一个简单的Java Applet应用程序
  20. C语言如何判断数独是否正确,会数独的大佬请进。这是个判断九宫格数独是否正确的程序。...

热门文章

  1. xmpp with openfire之一 xmpp and openfire
  2. TensorFlow 对数据集标记的xml文件解析记录
  3. html特殊字符的html,js,css写法汇总
  4. WinForm -- 为TextBox文本框添加鼠标右键菜单
  5. Django - 分页器
  6. 解题:洛谷2093 JZPFAR
  7. 请问Pycharm如何实现变量的批量重命名?
  8. 【BZOJ4545】DQS的trie 后缀自动机+LCT
  9. 怎样新建Oracle数据库
  10. (转)编写可重入和线程安全的代码(Writing Reentrant and Thread-Safe Code)