对权值线段树剪枝的误解--以HDU6703为例
引子
对hdu6703,首先将问题转化为“询问一个排列中大于等于k的值里,下标超过r的最小权值是多少”
我们采用官方题解中的做法:权值线段树+剪枝
对(a[i],i)建线段树,查询权值线段树的[k,n]中第一个下标超过r的值
代码是这样的
int ask(int l, int r, int root){
int mid = (l+r)>>1;
if(mx[root]<=R)return -1;
if(l==r){return l;}
int ans = -1;
if(k<=mid)ans=ask(lson);
if(ans==-1)ans=ask(rson);
return ans;
}
这把辣鸡的我给看meng了:在R=n的时候,最坏情况下一直向左递归,并且没找到然后向右递归,再向右递归的同时又重复没找到,这个ask不就退化成O(n)的了吗?
思考
经过半个月的思考(被虐),我大概懂了这个剪枝
首先分析以下几个问题:
什么情况下才会递归下去?
由代码第三行的
if(mx[root]<=R)return -1;
我们可以知道,只有当前权值区间\((l,r)\)的最大下标超过R才可能存在答案
什么情况下会往左递归并且不会从左边的递归返回答案?
假设当前权值区间为\([l,r]\)
如果往左边递归没有O(1)返回的话,根据上面的结论,那么一定是因为左区间\([l,mid]\)存在一个下标大于R
但是,左区间中合法区间应该为\([max(k,l),mid]\) **
所以当\(k>l\),且答案均分布在\([l,k]\)时,才会向左递归并且不从左区间返回答案**
什么时候“错误的左区间递归”会结束?
假设最坏情况,答案在k-1里,k-1一直在做区间的递归中,只有递归到当l=k的时候,才会结束这个错误
由线段树的相关性质只可以知道,这个最坏情况可以到\(l=r=k\),也就是跑了一个\(O(logn)\)的链
深入思考
思考完以上几个问题,继续思考:
当走完这条错误链,回溯的时候,会回溯到哪里?
当然是第一次出现这个错误分叉的地方(其实就是父节点)
但是此时我们在左区间没找到答案,会去右区间,而右区间\([mid+1,r]\)是完全包含于合法区间\([k,n]\)中的,所以只会出现两种情况
1.右区间没有合法答案,O(1)退出,继续回溯
2.右区间有答案,最终答案必在右区间中
一旦出现了2,就是正常的没有限制\([k,n]\)的线段树找最小值的O(logn)的做法了
而1也只是一个普通的回溯,按照父节点回溯到最原始的错误分叉,答案就在另一条路中
这个问题就解决啦
结论
这个剪枝强无敌,最终询问操作的执行次数只有两条链
复杂度为O(logn)
对权值线段树剪枝的误解--以HDU6703为例的更多相关文章
- 2019年CCPC网络赛 HDU 6703 array【权值线段树】
题目大意:给出一个n个元素的数组A,A中所有元素都是不重复的[1,n].有两种操作:1.将pos位置的元素+1e72.查询不属于[1,r]中的最小的>=k的值.强制在线. 题解因为数组中的值唯一 ...
- 【树状数组套权值线段树】bzoj1901 Zju2112 Dynamic Rankings
谁再管这玩意叫树状数组套主席树我跟谁急 明明就是树状数组的每个结点维护一棵动态开结点的权值线段树而已 好吧,其实只有一个指针,指向该结点的权值线段树的当前结点 每次查询之前,要让指针指向根结点 不同结 ...
- 【BZOJ-2892&1171】强袭作战&大sz的游戏 权值线段树+单调队列+标记永久化+DP
2892: 强袭作战 Time Limit: 50 Sec Memory Limit: 512 MBSubmit: 45 Solved: 30[Submit][Status][Discuss] D ...
- BZOJ 3110 ZJOI 2013 K大数查询 树套树(权值线段树套区间线段树)
题目大意:有一些位置.这些位置上能够放若干个数字. 如今有两种操作. 1.在区间l到r上加入一个数字x 2.求出l到r上的第k大的数字是什么 思路:这样的题一看就是树套树,关键是怎么套,怎么写.(话说 ...
- 动态求区间K大值(权值线段树)
我们知道我们可以通过主席树来维护静态区间第K大值.我们又知道主席树满足可加性,所以我们可以用树状数组来维护主席树,树状数组的每一个节点都可以开一颗主席树,然后一起做. 我们注意到树状数组的每一棵树都和 ...
- 线段树(单标记+离散化+扫描线+双标记)+zkw线段树+权值线段树+主席树及一些例题
“队列进出图上的方向 线段树区间修改求出总量 可持久留下的迹象 我们 俯身欣赏” ----<膜你抄> 线段树很早就会写了,但一直没有总结,所以偶尔重写又会懵逼,所以还是要总结一下. ...
- 【BZOJ3685】【zkw权值线段树】普通van Emde Boas树
原题传送门 因为马上要开始搞树套树了,所以学了一波权值线段树...毕竟是会点zkw线段树的,所以zkw线段树大法好! 解题思路: 介绍一下权值线段树吧,其实感觉就是线段树的本义,就是你用线段树维护了数 ...
- BZOJ_2161_布娃娃_权值线段树
BZOJ_2161_布娃娃_权值线段树 Description 小时候的雨荨非常听话,是父母眼中的好孩子.在学校是老师的左右手,同学的好榜样.后来她成为艾利斯顿第二 代考神,这和小时候培养的良好素质是 ...
- BZOJ_3685_普通van Emde Boas树_权值线段树
BZOJ_3685_普通van Emde Boas树_权值线段树 Description 设计数据结构支持: 1 x 若x不存在,插入x 2 x 若x存在,删除x 3 输出当前最小值,若不存 ...
随机推荐
- 利用Python进行数据分析学习记录(一)
1.Python的科学计算邮件列表 pydata:这是一个Google Group邮件列表,其中的问题都是Python数据分析和pandas方面的. pystatsmodels:针对Numpy相关的问 ...
- .NET Core 3 WPF MVVM框架 Prism系列之模块化
本文将介绍如何在.NET Core3环境下使用MVVM框架Prism的应用程序的模块化 前言 我们都知道,为了构成一个低耦合,高内聚的应用程序,我们会分层,拿一个WPF程序来说,我们通过MVVM模式 ...
- 【转】在NetBeans上搭建Android SDK环境
本文将介绍在NetBeans 6.8上搭建Android SDK环境,目前Android在Netbeans上进行开发需要借助nbandroid的平台插件. 我们刚刚介绍过<MyEclipse上搭 ...
- 简单工厂模式(C++)
#include <iostream> using namespace std; class Fruit { public : ; }; class Banana :public Frui ...
- echarts更改轴线颜色
xAxis : [ { type : 'category', data : ['1月','2月','3月','4月','5月','6月','7月','8月','9月','10月','11月','12月 ...
- 简单 hash 入门题目
题目描述 NOIP 复赛之前,HSD 桑进行了一项研究,发现人某条染色体上的一段 DNA 序列中连续的 kkk 个碱基组成的碱基序列与做题的 AC 率有关!于是他想研究一下这种关系.现在给出一段 DN ...
- 执行sql中的 函数,function
CREATE FUNCTION [dbo].[GetWeight] ( ,)--重量/体积重 ) ,) as begin --顺丰重量/体积重以0.5kg为单位向上取值(小数点后两位4舍5入) ,) ...
- 256位AES加密和解密
/// <summary> /// 256位AES加密 /// </summary> /// <param name="toEncrypt">& ...
- Java多线程的创建(一)
方法一:继承Thread类实现 1.创建一个类A,并继承Thread类 2.重写A的run()方法 3.创建A的实例对象b,即创建了线程对象 4.使用b调用start()方法:启动线程(会自动调用ru ...
- numpy 读取数据
一.CSV文件 CSV: Comma-Separated Value,逗号分隔值文件 显示:表格状态 源文件:换行和逗号分隔,逗号 列,换行 行 二.读取数据 1.方法 loadtxt(fname, ...