首页 > 其他分享 >关于分治法左右区间单调遍历应该如何设计

关于分治法左右区间单调遍历应该如何设计

时间:2024-11-11 22:44:33浏览次数:3  
标签:遍历 res 分治 right 区间 元素 left 单调 指针

阅读以下文章,首先至少要求通过一道分治法的题目或听过一道该类型的讲解。

对于分治的题目,想必你应该知道,通常我们是对于一个区间拆分两个部分,而最小子问题通常是只包含一个元素的区间数组。为了后续方便处理更大范围的区间,通常在处理该小区间后,我们会将其区间内元素排序,例如下面例子:

该例子是求:对于右区间的每个元素,求右侧大于左侧的元素个树,比如左数组为 2 3 右数组为:4 3,那么对于4来说2 3 两个都比4小,对于右侧的3来说只有2比他小,所以结果为3
在这里插入图片描述

很显然,我们可以使用两个指针,暴力遍历所有,直接求出答案,而该代码的时间复杂度为O( n 2 n^2 n2)

public static int GetKey(){
	int res=0;
	for(;left<mid=;left++){
			for(;right<=n;right++){   //n为区间最右端
					res+=num[right]>num[left]?1:0; //满足则加1,不满足则不加
				}
		}
	return res;
} 

在一次期末考试后,班主任决定颁发奖励,满足一定方式的学生都可以获得某个等级的奖励,对于分数高的同学既可以获取一等奖,也可以获取二,三等奖。聪明的班主任想到快速的方法分配奖励,他先将分数从低到高排序,他先从低级奖励分配,每次分配奖励,他先看看学生的分数,由于学生分数以排序,从左往右数,直到找到满足分数的学生,剔除前面的学生,毕竟连当前奖励分数都不满足,那么必定与后面的奖励无缘了,每分配下一等级的奖励,他都循环这一步骤。
这个故事是有一定的开导性的。
自然可以想到一种更好的方法了(对于有单调性的题目一般都可以,所谓单调性是:如果a>b,b>c,一定有a>c)
那就是左右两侧都先排序,利用有序性,则可以减少大部分的计算,例如下图

1.右指针指向的元素是大于左指针指向的元素,由于排序后,右指针后面的其实都大于左指针指向的元素,所以大于23的右侧元素个数为区间右端减去右指针再加1。
2.然而聪明的你意思到,这并不对,因为你怎么确定右指针的左侧不会有比23大的树呢,其实对于左右指针的控制确保了右指针的前面不会存在比左指针大的情况的。在这里插入图片描述

public static int GetKey(){
	for(;left<=mid;left++){          //遍历每一个需要满足的条件
			while(right<n&&num[right]<=num[left]){      //向右寻找满足条件的元素
					right++;           
				}
			if(right<n){       //如果有满足元素的话
					res+=n-1-right+1;     //n-1代表区间最右下标
				}
			else{
					break;  //当前过滤的没有满足的元素了,那么后面更不可能了
				}
		}	
	return res;
}

仔细观察该代码,是不是发现右指针前面的元素一定不会大于左指针的呢!

刚学完,来试试可不可以立即想到一种解决方案,毕竟不是所有题的单调性都是这么直观的。
数组还是上面的图片,但是条件换为num[left]>num[right]*2。

这与上面的题目类似,只不过是左右大小条件换了,变成左侧大于右侧,那么你可以把条件当作右侧,分数当作左侧(引用上面的故事)。

以下是答案

public static int GetKey(){
	for(;right<n;right++){
			int res=0;
			while(left<=mid&&num[left]<=num[right]){
					left++;
				}
			if(left<=mid){
					res+=mid-left+1;
				}
		}
	return res;
}

标签:遍历,res,分治,right,区间,元素,left,单调,指针
From: https://blog.csdn.net/2303_78983004/article/details/143695227

相关文章

  • 决策单调性 dp
    重修!updon09/14/24:狗屁模拟赛督促我来更新这篇博。以下讨论最小化问题。对于\(n\timesn\)的矩阵,有:子矩阵\(A_{[i_1,i_2,..,i_k][j_1,j_2,..,j_\ell]}\)为矩阵\(A\)取出\(i_1,i_2,..,i_k\)行和\(j_1,j_2,..,j_\ell\)组成的矩阵。其中当序列\(i,j\)元素连续时......
  • 郝玩的数据结构1——单调栈,单调队列
    栈和队列是很郝咏的Stl,那么,我们手搓——用数组模拟故事背景:辣鸡老o在学单调栈&单调队列——我栈top为栈顶,易得出出栈即top--,入栈++top=(ovo)......——完全不会讲,那么上马:点击查看代码#include<bits/stdc++.h>usingnamespacestd;constintN=114514;intstk[N],top=0;......
  • 4-5-1.C# 数据容器 - Stack(Stack 的定义、Stack 元素的基本操作、Stack 元素的遍历、S
    Stack概述Stack<T>遵循后进先出的规则存储元素Stack<T>支持泛型,可以指定存储的元素的类型Stack<T>不是线程安全的,在多线程环境中需要谨慎使用一、Stack的定义定义StackStack<int>nums=newStack<int>();定义Stack并填充一些元素Stack<int>nums......
  • 4-4-1.C# 数据容器 - Queue(Queue 的定义、Queue 元素的基本操作、Queue 元素的遍历、Q
    Queue概述Queue<T>遵循先进先出的规则存储元素Queue<T>支持泛型,可以指定存储的元素的类型Queue<T>不是线程安全的,在多线程环境中需要谨慎使用一、Queue的定义定义QueueQueue<int>nums=newQueue<int>();定义Queue并填充一些元素Queue<int>nums=......
  • 4-3-1.C# 数据容器 - Dictionary(Dictionary 的定义、Dictionary 元素的基本操作、Dict
    Dictionary概述Dictionary<TKey,TValue>存储的是键值对(Key-Value),通过键(Key)来存储或修改值(Value)Dictionary<TKey,TValue>存储的键值对是无序的Dictionary<TKey,TValue>存储的键是不可重复的Dictionary<TKey,TValue>支持泛型,可以指定存储的键值对的类型D......
  • leetcode1008. 前序遍历构造二叉搜索树
    给定一个整数数组,它表示BST(即 二叉搜索树 )的 先序遍历 ,构造树并返回其根。保证 对于给定的测试用例,总是有可能找到具有给定需求的二叉搜索树。二叉搜索树 是一棵二叉树,其中每个节点, Node.left 的任何后代的值 严格小于 Node.val , Node.right 的任何后代的值......
  • 单调栈基础模板
    #include<bits/stdc++.h>usingnamespacestd;constintN=1000005;intn,ansl[N],ansr[N],a[N];intf[N],r,x;intmain(){cin>>n;for(inti=0;i<n;i++)cin>>a[i],ansl[i]=ansr[i]=-1;for(inti=0;i<n;i++){......
  • ABC372D ABC379F 题解 单调栈二分
    ABC372DABC379F题解单调栈二分一直觉得AT上面学到的东西比CF要多一些,无意捧一踩一,但可能是我太菜的原因,毕竟ABC的题目普遍要比Div.2简单一些。好多次碰到这个单调栈里面二分的trick了,所以写一篇来总结一下。ABC372D形象地给定一系列Buildings的高度\(h\),保证每个......
  • 单调队列笔记
    单调队列笔记双端队列deque维护一个严格单调变化的组,可以称为一个单调队列单调队列因为可以直接对组的两端进行操作,所以可以有效的降低时间复杂度用单调队列来解决问题,一般是需要得到的某个范围内的最小值或最大值这里以一道经典的单调队列的题目为例:题目描述有一个长为\(......
  • 4-2-2.C# 数据容器 - HashSet(HashSet 的定义、HashSet 元素的基本操作、HashSet 元素
    HashSet概述HashSet<T>存储的元素是无序的HashSet<T>存储的元素是不可重复的HashSet<T>支持泛型,可以指定存储的元素的类型HashSet<T>不支持索引,不可以通过索引获取或修改元素HashSet<T>不是线程安全的,在多线程环境中需要谨慎使用一、HashSet的定义定义......