【原创】线段树query模板对比! 新手线段树的一个容易出错的问题!!因为我就糊涂了一整天..........

【原创】线段树query模板对比! 新手线段树的一个容易出错的问题!!因为我就糊涂了一整天.......

 

我们解决问题的最好方法就是拿实例来举例子

我们来看tyvj1038或计蒜客 “管家的忠诚”

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

输入中第一行有两个数m,n表示有m(m< =100000)笔账,n表示有n个问题,n< =100000。 第二行为m个数,分别是账目的钱数 后面n行分别是n个问题,每行有2个数字说明开始结束的账目编号。

输出文件中为每个问题的答案。具体查看样例。

 

样例输入

<span style="color:#993366">10 3
1 2 3 4 5 6 7 8 9 10
2 7
3 9
1 10
</span>

样例输出

<span style="color:#993366">2 3 1

<span style="color:#000000">一道最最最基础的线段树的题,<span style="color:#ff0000">单点更新,<u>求区间最小值</u></span>,我们先来看两组代码,是两个不同的查询函数(query).

</span></span>
 
1 struct nod
2 {
3     int l,r;
4     int data;
5 }tree[5*N];
 block 1:
 1 int query(int i,int l,int r)
 2 {
 3 
 4     if(l<=tree[i].l&&tree[i].r<=r)
 5     {
 6         return tree[i].data;
 7     }
 8     int mid=(tree[i].l+tree[i].r)/2;
 9     int ret = 99999999;
10     if(l<=mid)
11         ret = min(ret,query(i*2,l,r));
12     if(r>mid)
13         ret = min(ret,query(i*2+1,l,r));
14     return ret;
15 }
来先看一下block 1 的10和12行,再对比一下block 2 的8和10行,是不是发现l和r反了呢?
到底哪个是对的,哪个是错的?
 block 2:
 1 int query(int i,int l,int r)
 2 {
 3     if(l<=tree[i].l&&tree[i].r<=r)
 4     {
 5         return tree[i].data;
 6     }
 7     int mid=(tree[i].l+tree[i].r)/2;
 8     if(r<=mid)
 9         return query(i*2,l,r);
10     if(l>mid)
11         return query(i*2+1,l,r);
12     return min(query(i*2,l,r),query(i*2+1,l,r));
13 }

 

我一开始学线段树的时候,也就是昨天...想找一个好一点的模板,但发现这两个模板好像不太一样,r和l完全是反的,尼玛!这肯定有一个是错的啊,这尼玛写错了不是误人子弟!!!幸好老夫多看了几个模板,要不然就被坑死了!!

随着时间的推进,窝终于对线段树的理解越来越深,终于茅塞顿开!原来两个都是对的~~

我现在来解析一下:

block 2是我采用的类型,第8行的意思是如果你查询的右端都小于当前区间的mid了,那当前区间的data(视题目而定),肯定全部由左孩子过来的,直接返回左孩子的值,和右孩子没卵关系!第10行同理

 

block 1是老师采用的类型,第10行的意思是只要你查询区间的左端小于当前区间的mid,那肯定有一部分是从左孩子来的,我先把你和ret比较一下,最小值记录到ret里,12行的意思,只要你查询区间的右端大于当前区间的mid,那肯定有一部分是从右孩子来的,我再把你和当前ret比较一下,最小值记录到ret里。最后我再输出ret。

 

觉得怎么样呢,理解了没有?没有理解做一下这道题吧,理解会更深~

附上我的题解http://www.cnblogs.com/liwenchi/p/5760660.html

<span style="color:#993366"><span style="color:#000000"> </span></span>
 
 
 
 
 
 
 
posted @ 2016-08-11 15:50 swallowblank 阅读(...) 评论(...) 编辑 收藏
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值