关于划分树

车载测试工程师必备:5分钟搞定CANoe台架搭建(附DBC导入技巧) 本文为车载测试工程师提供快速搭建CANoe测试台架的实用指南,涵盖硬件连接、DBC文件导入及常见报错解决方案。通过详细步骤和高效技巧,帮助工程师在5分钟内完成台架搭建,提升车载测试效率,特别适合紧急功能验证场景。 阅读详情

从昨天晚上一直到今天,我都在纠结划分树……TMD打错变量害死人……我还一直以为划分树哪里写错了……


划分树可以在O(nlogn)的时间内建树(常数巨大……),在logn的时间内求出一个区间内的第k小数(求第k大就改一下建树时的偏序关系)

怎么样做呢,HH大牛的blog上有一篇日志的图非常好……

此图片转载自http://www.notonlysuccess.com/index.php/divide-tree/

val[0]为初始序列,sorted为初始序列排序后的序列,sorted是为了方便的找到中位数

然后对于每一层的每个区间,找到这个区间的中位数,小于它分左边,大于它分右边,如图

然后对于每一层每个区间的每个点,记录这个点所在的区间到这个点为止有多少个数分到了左边


有一个问题,就是如果划分的时候碰到跟中位数相等的数怎么办呢

有两种办法,一种是先离散成1-n的排列,

还有一种办法是事先扫一遍这个区间,求得有多少个数与中位数相等,应该分多少个到左边去

第二种方法的常数会比第一种大,但是我一般不喜欢写离散(尽管就几行代码),使用哪种就看个人喜好了

/*

我曾经以为可以记一个same数组,这样可以快速得到这个区间里面有多少个数和中位数相等,加快速度

这种方法可以通过poj2104,但是实际上是错误的,在数据较大的情况下有较低概率出错,这证明poj2104数据太水

*/




而询问实际上就是一个不断逼近的过程,六元组(l,r,x,y,k,h)代表现在在树上第h层,l-r这个区间,询问x,y之间的第k小

由于建树时记录的信息,可以轻松求出x-y之间有多少个数被放到了下一层的左边,记为ss

如果ss>=k,那么去下一层的左子树找,否则去右子树找,根据这些信息也可以得到下一层的x,y(具体看代码)


可以发现query的过程只用到了build当中的  记录下一层有多少个在左边  的信息

所以划分树本身是可以开成滚动的



自认为自己的划分树还是写的比较好看的

核心代码30行不到(这里划分树没有开成滚动,滚动实测好像会慢一点)   poj2104:

//Lib
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<ctime>

#include<iostream>
#include<algorithm>
#include<vector>
#include<string>
#include<queue>
using namespace std;
//Macro
#define rep(i,a,b) for(int i=a,tt=b;i<=tt;++i)
#define rrep(i,a,b) for(int i=a,tt=b;i>=tt;--i)
#define erep(i,e,x) for(int i=x;i;i=e[i].next)
#define irep(i,x) for(__typedef(x.begin()) i=x.begin();i!=x.end();i++)
#define read() (strtol(ipos,&ipos,10))
#define sqr(x) ((x)*(x))
#define pb push_back
#define PS system("pause");
typedef long long ll;
typedef pair<int,int> pii;
const int oo=~0U>>1;
const double inf=1e20;
const double eps=1e-6;
string name="input",in=".in",out=".out";
//Var
int s[20][200008],d[20][200008],n,m,sorted[200008];
void Init();
void Work();
void Build(int l,int r,int h);
int Query(int l,int r,int x,int y,int k,int h);
int main()
{
	Init();
	Work();
	return 0;
}
void Init()
{
	scanf("%d%d",&n,&m);
	rep(i,1,n)scanf("%d",&d[1][i]),sorted[i]=d[1][i];
	sort(sorted+1,sorted+1+n);
	Build(1,n,1);
}
void Work()
{
	int x,y,k;
	rep(i,1,m)
	{
		scanf("%d%d%d",&x,&y,&k);
		printf("%d\n",Query(1,n,x,y,k,1));
	}
}
void Build(int l,int r,int h)//d数组为划分树,s数组为分多少到下一层左边的
{
	if(l==r)return;
	int mid=l+r>>1,cnt=mid-l+1,smid=sorted[mid],lpos=l,rpos=mid+1,pos=0;
	rep(i,l,r)if(d[h][i]<smid)cnt--;
	rep(i,l,r)
	{
		if(d[h][i]<smid||d[h][i]==smid&&cnt)
		{
			pos++;if(d[h][i]==smid)cnt--;
			d[h+1][lpos++]=d[h][i];
		}
		else d[h+1][rpos++]=d[h][i];
		s[h][i]=pos;
	}
	Build(l,mid,h+1);
	Build(mid+1,r,h+1);
}
int Query(int l,int r,int x,int y,int k,int h)
{
	if(l==r)return sorted[l];
	int mid=l+r>>1,l1,l2;
	l1=(l==x)?0:s[h][x-1];
	l2=s[h][y];
	if(k<=l2-l1)return Query(l,mid,l+l1,l+l2-1,k,h+1);
	else return Query(mid+1,r,mid+1+x-(l+l1),mid+1+y-(l+l2),k-(l2-l1),h+1);
}


dht11在oled上显示温度 stm32l432kc,如何实现? 🏆 本文收录于《全栈Bug调优(实战版)》专栏,致力于分享我在项目实战过程中遇到的各类Bug及其原因,并提供切实有效的解决方案。无论你是初学者还是经验丰富的开发者,本文将为你指引出一条更高效的Bug修复之路,助你早日登顶,迈向财富自由的梦想🚀!同时,欢迎大家关注、收藏、订阅本专栏,更多精彩内容正在持续更新中。让我们一起进步,Up!Up!Up!    备注: 部分问题/难题源自互联网,经过精心筛选和整理,结合数位十多年大厂实战经验资深大佬经验总结所得,数条可行方案供所需之人参考。 阅读详情

相关推荐

A Side Scan Sonar Image Denoising Algorithm Based on Compound of Fuzzy Weighted Average and Kalman F

Abstract 水下侧扫声纳图像的噪声来源:高斯噪声、脉冲、斑点噪声。 传统方法只能移除部分噪声,并且去噪后容易造成细节模糊。 本文在考虑到噪声的随机性以后,提出一种融合了模糊加权平均和卡尔曼滤波的去噪方法。 在最大化保留图像细节的基础上,同时去除高斯噪声和脉冲噪声 一.Introduction 由于海底环境和声波自身干涉的影响,声纳图像生成的图像难免会有噪点。声纳采集的图像通常会有高斯噪声、脉...

qq_44516871的博客 927

划分树·详解·模板

用划分树来解决选定区间内的第K大值,其实也就两步!一步是建树,另一步则是查询。      先说我对建树的理解吧!     建树的过程很简单:两步就OK了!    第一步:找到序列的中位数,把大于中位数的扔到中位数的左边,小于中位数的扔到数的右边。这样整个序列就被分成了两个区间。    第二步:对每个子区间,也分别执行第一步操作,直到序列中只有一个元素为止。    可以

wishcxz_acm 683

从一根USB线缆说起:深入浅出聊聊那些影响信号完整性和EMC性能的‘小细节’(双绞、屏蔽、360度搭接全解析)

本文深入探讨了USB线缆中影响信号完整性和EMC性能的关键细节,包括双绞线绞距、屏蔽层设计和360度搭接工艺。通过实验数据和实用技巧,揭示了这些‘小细节’如何显著影响高频信号质量和电磁兼容性,为工程师提供了从选购到系统设计的全面指南。

weixin_30824479的博客 439

划分树--详解

看了一些博客,感觉有些博客对建树写的挺好,但是对于查询区间却一笔带过。在看懂了之后决定自己写一篇,加深自己的理解,也希望对正在学习划分树的人能够有所帮助。 如有错误,敬请大佬指出。 进入正题: 有这样一类题目,求的是区间内的第k大数。 划分树的定义就是对整体的区间进行划分,把相对于原来序列中较小的值放在左子树,较大的放在右子树,最后按照它的性质进行查询以此找到要查询的区间里的第k大数。 ...

Akatsuki 1919

Unity程序化河流生成工具Waterways:从算法到实践的全流程解析

程序化内容生成(PCG)是游戏开发与三维建模领域的关键技术,它通过算法自动创建游戏内容,显著提升开发效率。其核心原理是将设计规则转化为可执行的代码逻辑,从而生成复杂、多样且符合自然规律的环境资产。在开放世界游戏和模拟经营类项目中,程序化生成技术能够快速构建大规模、高一致性的自然场景,如山川、森林与水体网络。Unity引擎作为广泛使用的开发平台,其地形系统与着色器管线为程序化工具的集成提供了强大基础。本文聚焦于利用Waterways这一Unity工具集,深入探讨如何通过模拟重力驱动、流量累积等自然水力原理,在

weixin_33690963的博客 684

从零到一:Abaqus与Matlab联合仿真的自动化流程构建指南

本文详细介绍了如何构建Abaqus与Matlab联合仿真的自动化流程,涵盖基础架构设计、关键接口技术实现、结果提取与处理技术以及高级参数化优化流程。通过Python脚本作为桥梁,实现数据传递和任务控制,帮助工程师提升仿真效率。特别强调了版本兼容性、异常处理和性能监控等实用技巧。

weixin_29090089的博客 612

K-th Number POJ - 2104 (主席树 | 划分树)(附动态区间主席树模板)

K-th Number POJ - 2104 You are working for Macrohard company in data structures department. After failing your previous task about key insertion you were asked to write a new data structure that would...

weixin_44090305的博客 1646

PCL点云库入门(第6讲)——PCL库中Eigen数学工具库的基本使用(持续更新)

Eigen库是一个高性能的C++模板库,专注于线性代数、矩阵和向量运算,以及相关的数值分析和算法。在Eigen库中,所有的矩阵和向量均被视为矩阵模板类的实例。向量可以被看作是特殊形式的矩阵,具体表现为只包含1行或1列。

qq_36812406的博客 1752

划分树

对于区间第k大值,除了我们之前介绍的归并树之外。现在要登场的数据结构将比归并树的效率更高,他就是划分树。我们学习归并树的时候了解到:归并树 = 线段树 + 归并排序。那么我们今天要介绍的划分树就是:线段树 + 快排。要说有什么不同的,那就是归并树是从有序到无序,而划分树是从无序到有序。 1、划分树的定义         给定一序列a[1...n],sorted[1...n]为序列从小到大的排列

Enstein_Jun 4020

基于STM32F103的智能门禁门锁门卫系统设计

本文设计了一种基于STM32F103单片机的智能门禁系统,集成了密码、射频IC卡和指纹识别三种验证方式。系统采用模块化设计,包含MFRC522射频模块、AS608指纹模块、矩阵键盘、OLED显示和舵机控制等硬件,实现了身份验证、密码修改、IC卡/指纹管理以及安全防护功能。测试结果表明系统响应迅速(密码验证250ms、指纹验证600ms)、功耗低(待机50mA),且具备掉电密码保存功能。该系统操作简便、功能完善,适用于家庭和办公场所,具有较高实用价值。未来可扩展远程控制、人脸识别等功能以进一步提升智能化水平。

3254968421的博客 318

Java SSH框架学习

Java SSH框架学习

私信可回答各种问题~ 1789

【划分树】

划分树和归并树都是用线段树作为辅助的,原理是基于快排 和归并排序 的。 划分树的建树过程基本就是模拟快排过程,取一个已经排过序的区间中值,然后把小于中值的点放左边,大于的放右边。并且记录d层第i个数之前(包括i)小于中值的放在左边的数。具体看下面代码注释。 查找其实是关键,因为再因查找[l,r]需要到某一点的左右孩子时需要把[l,r]更新。具体分如下几种情况讨论: 假

leolin_的专栏 1297

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

数据结构----划分树

今晚又学了另外一种树----划分树。看了一晚上了,也是大概明白一些而已,对于一些细节还是不太理解。 划分树是一种基于线段树的数据结构。主要用于快速求出(在log(n)的时间复杂度内)序列区间的第k大值 。(主席树也可以,早就听过主席树这个词,感觉好高大上,准备学习一下,下面的例题也是主席树入门) 划分树的定义          划分树定义为,它的每一个

Lin_disguiser的博客 2725

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

划分树小结

最近学习了一下划分树,下面总结一下。 我们在求区间最值的时候,一般可以用线段树解决,但是如果要求区间第k小或者第k大值的话线段树就有点力不从心了,这是我们可以用划分树来解决。划分树利用了快速排序的思想,首先是建树,我们设当前区间的中位数为mid,(为了能快速找到区间的中位数,我们一般先对原序列做一次排序)则我们将区间中比mid小的放入左子树,将区间中比mid大数的放入右子树中,和mid相等的要讨

ddyyxx的程序员之路 2281

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

【划分树】求区间K大数

<br />       求区间K大数,众所周知有二分答案+树套树的做法,每个询问复杂度为O(log3N),可谓近似一个O(N)了,不仅时间复杂度高,编程复杂度也不低,后来才发现还有一种叫划分树的数据结构,专门做这种问题。<br />      本来觉得知道个树套树就够了,据我所知划分树还不支持区间修改操作,但是这次NOI一试的piano偏偏那出题人就有这么重口味,给你来两个500000的点!真是不简单,当时我都在想有没有O(N)的算法了。树套树的复杂度偏偏就被卡掉了,三个点平均每个点要跑5秒,好吧,那就学

Evil.livE 4382

HDU 2665 Kth number(划分树)

题目链接:点击打开链接 思路:划分树模板题。 细节参见代码: #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define Max(a,b) ((a)>(b)?(a):(

AC_Arthur的专栏 4524

划分树笔记

划分树笔记 问题模型: 对于给定的n个元素的序列A,有m次询问,每次询问给L ,R,K,请求出位于[L,R]内第K大的数。 解题思路: 朴素算法: 用快速排序。由于我们有m次询问,而每次询问区间左右端点是不同的,故如果对每个询问进行排序,我们在得到答案后还需要将序列恢复原状。按照快速排序的效率O(nlgn),m次询问就是O(mnlgn)。如果m和n都很大,效率就低的可怜。 划分树: 由于划分树...

帅比王的博客 414

划分树讲解

划分树是专门用来求静态区间第k的一种数据结构 它主要利用快排的思想来进行建树和查询 比如给你一个长度为12序列{1,9,4,5,8,3,4,6,5,2,5,7} 我们要按照划分树来建树该怎么建呢 1.首先和快速排序一样,分而治之。   我们把平均分为两部分,左区间任何一个数都小于右区间的一个数    同时左右两个区间的序列顺序和原来区间一样   我们还需要统计一下对于原区间[l,r]的任意一个数b...

唐宋元明清的博客 499

划分树板子

划分树 划分树通过模拟快速排序的过程,每次将数据分为2部分,小的部分和大的部分,并且相同的数在序列中的位置在划分之后相对位置依然不变,通过维护num数组计算当前位置和之前的数有多少个数被分入左子树。具体教程详见博客:划分树 划分树模板 求区间第k小,同样求区间第k大可以转化为求区间[l, r]的第(r-l+1-k+1)小。 #include <cstdio> #include <...

你真的介意真的在乎真的想要真的渴望的话你一定能够做到 302
上一篇: NOI2010.Day1.T2.超级钢琴
下一篇: [Sdoi2008]Cave 洞穴勘测
OrpineX
博客等级 码龄17年 16粉丝 68原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值