Skip to content

把这些转为markdown源码给我:

kth问题总结

定义:
	所谓Kth问题,就是给定了一个集合,让你从中选出价值第k大/小的元素来,可以分为输出方案型和输出价值型
处理办法:
	法一:二分价值,可以处理任意大小K的情况
		两种处理办法:
			法一:转化成离线DS问题
			法二:利用构造解的O(K)做法
		注意:
		1.涉及字典序的,一般都是逐位考虑,然后结合二分(或者均摊)确定该位的值
		2.如果价值不好算、只有偏序关系的话,可以随机n个元素来二分,然后用法二
	法二:结合堆进行贪心构造,处理k比较小的情况
		优点:
			处理二分处理不了的问题
			复杂度可能更优
		构造注意:
		1.确保每个解都能被构造到(最好是唯一被构造到)
		2.确保对于每个解,比其更优的解都先被构造了
			(每个解都对应了若干后继,且后继不优于当前解)
		
		其实,解的构造关系构成了一棵树(堆)
		
		Alex_Wei的阐述:
		这类 “不断扩展结构,取出权值前k小” 的问题非常经典,其解法如下:
		对每个除了权值最小的结构,为其钦定一个权值不比它大的前驱,满足前驱关系不成环。
		这样,任何结构都可以从唯一的无前驱的权值最小的前驱开始扩展得到,满足每次扩展一个前驱为当前结构的结构,即每次扩展一个后继。
		用优先队列维护所有被扩展但未被考虑的结构,第k次取出队列中权值最小的结构即权值第k小的结构,然后将其所有后继加入优先队列。
	
	注意:不要思维固化,认为k小一定是调整,有的时候调整比二分更难写
刷题:
区间kth问题:
	如果是法二,一般都是定右端点考虑左端点怎么保证单调性(即注意2)
	P2048,P5283:两个方法都能用
		可以发现,法一会比法二复杂度多一个log
		P2048的法一需要用到主席树,好像没什么人写
	OIFC's problem:
		定义可重集 A 比可重集 B 小,当且仅当对于 在两个可重集中出现次数不同的最小元素 x ,元素 x 在 A 中出现次数更多。
		给定一个序列 a1∼n​ 。对于每一个 1≤l≤r≤n,可以对应一个可重集 al,al+1,…,ar。
		这样可以生成 n(n+1)/2 个可重集。
		给定正整数 k 。问在这些可重集中,第 k 小的是哪个。
		lim:n<=1e5,k<=n*(n-1)/2
		
		solution:
			先考虑偏序怎么确定,这可以主席树
			直接二分没法做,因为权值不确定,所以随机n个区间,然后二分
			那么考虑法二怎么做,可以发现有包含关系的区间就有偏序关系,那就做完了
			注意在二分判定时可以直接双指针,去掉一个log
字典序kth问题:
	简单题:字典序第K小排列
	联合省选2024 DAY2 T1
	
	自造题:
		给定一棵带标号无根树,求第k小的先序遍历序列。lim:n<=5e5,k<=1e18
		solution:
		先考虑确定出发点。考虑以i为根,那么可行的序列数是所有非叶节点的儿子数的阶乘的乘积,记作f[i]
		显然这东西非常大,在n>=100的时候肯定只能从1出发
		所以我们直接暴力从小到大枚举根节点,然后跑一遍树形DP算一下可行解,就可以知道目标序列的第一个点的标号
		注意这里不能换根,因为答案太大了
		考虑现在要从根开始,我走了其中某个儿子i,那么对应的序列数量是f[rt]/sons
		那么从小到大枚举一下儿子,找到第K大序列的第二个点的标号
		类似的,我们可以一直递归做下去
		然后考虑回溯以后怎么办,把已经递归了的部分的f的贡献直接除掉,执行刚才的步骤即可
		复杂度O(n*(logV+logn)+100*100)
		详见Problem3
	
	发现的题:
		有一棵包含N个节点的二叉树,节点编号是1~N。
		现在我们知道它的中序遍历结果A1, A2, ... AN。
		问先序遍历字典序第K小的二叉树
		
	模拟赛题:
		平面内曼哈顿距离前K小距离
		
		曼哈顿距离转切比雪夫距离,发现有一个很傻的处理办法,就是直接维护出每个点在下面的情况能贡献的最小点对,可以用树套树结合二分进行调整(确实是可行的)
		考虑怎样更好写,显然树套树应该要用离线弄掉去,但这根本没法离线
		考虑二分,那么就可以用扫描线替换树套树。这里要用不unique的离散化,结合BIT即可
		然后,我们得到了第K小距离,那怎么得到最后的具体输出呢?
		考虑到第k小距离可能对应了很多点对,所以我们取其减一的值,再跑一遍二分时的check,然后将剩下的随便填上即可
		此时check的实现应该可以暴力一点,用set代替BIT
		
选数kth问题:
	tsingcheng's problem:
		从n个数中选若干(至少1)个数求和,求所有方案中第k小的和(和相同但取法不同的视为不同方案)
		lim:n<=1e5,k<=5e5
		
		solution:
		直接考虑法二,发现可以直接每次把最后一个值往后移一位,或是在最后一个值后面再加一个,那么就做完了
	P2483 k短路:
		首先考虑如何调整,可以发现必然是从最短路的末尾一段分叉,走向另一条最短路,发现这就是最短路树选非树边的过程
		看一下怎么暴力实现调整,最短路长度不太好算,考虑直接将非树边的权值重新赋一下
		那么就转化成选若干非树边,使其和第k小,这就是选数kth问题
		但注意到非树边之间有一些祖先关系,所以以此为顺序调整,可以把当前的最后一条边调整成次短边,或是直接新选一条边
		这需要我们维护后继,可以用可持久化实现,例如主席树结合二分
		特别注意,这里有重复元素,而我们要维护后继,可以用不unique的离散化实现钦定相等元素之间的顺序
	题意:给 n 个数,每次选出一个大小在 [L,R] 之间的子集,求前 k 大的子集和的和. n,k≤2×10^5.
		solution:
		从小到大排序,先考虑大小为len的集合
		调整应该是选出一段后缀向右平移一格
		多种大小分别维护即可
		结合堆实现即可
		
		类似题:CF1250I,P6646
定义:
	所谓Kth问题,就是给定了一个集合,让你从中选出价值第k大/小的元素来,可以分为输出方案型和输出价值型
处理办法:
	法一:二分价值,可以处理任意大小K的情况
		两种处理办法:
			法一:转化成离线DS问题
			法二:利用构造解的O(K)做法
		注意:
		1.涉及字典序的,一般都是逐位考虑,然后结合二分(或者均摊)确定该位的值
		2.如果价值不好算、只有偏序关系的话,可以随机n个元素来二分,然后用法二
	法二:结合堆进行贪心构造,处理k比较小的情况
		优点:
			处理二分处理不了的问题
			复杂度可能更优
		构造注意:
		1.确保每个解都能被构造到(最好是唯一被构造到)
		2.确保对于每个解,比其更优的解都先被构造了
			(每个解都对应了若干后继,且后继不优于当前解)
		
		其实,解的构造关系构成了一棵树(堆)
		
		Alex_Wei的阐述:
		这类 “不断扩展结构,取出权值前k小” 的问题非常经典,其解法如下:
		对每个除了权值最小的结构,为其钦定一个权值不比它大的前驱,满足前驱关系不成环。
		这样,任何结构都可以从唯一的无前驱的权值最小的前驱开始扩展得到,满足每次扩展一个前驱为当前结构的结构,即每次扩展一个后继。
		用优先队列维护所有被扩展但未被考虑的结构,第k次取出队列中权值最小的结构即权值第k小的结构,然后将其所有后继加入优先队列。
	
	注意:不要思维固化,认为k小一定是调整,有的时候调整比二分更难写
刷题:
区间kth问题:
	如果是法二,一般都是定右端点考虑左端点怎么保证单调性(即注意2)
	P2048,P5283:两个方法都能用
		可以发现,法一会比法二复杂度多一个log
		P2048的法一需要用到主席树,好像没什么人写
	OIFC's problem:
		定义可重集 A 比可重集 B 小,当且仅当对于 在两个可重集中出现次数不同的最小元素 x ,元素 x 在 A 中出现次数更多。
		给定一个序列 a1∼n​ 。对于每一个 1≤l≤r≤n,可以对应一个可重集 al,al+1,…,ar。
		这样可以生成 n(n+1)/2 个可重集。
		给定正整数 k 。问在这些可重集中,第 k 小的是哪个。
		lim:n<=1e5,k<=n*(n-1)/2
		
		solution:
			先考虑偏序怎么确定,这可以主席树
			直接二分没法做,因为权值不确定,所以随机n个区间,然后二分
			那么考虑法二怎么做,可以发现有包含关系的区间就有偏序关系,那就做完了
			注意在二分判定时可以直接双指针,去掉一个log
字典序kth问题:
	简单题:字典序第K小排列
	联合省选2024 DAY2 T1
	
	自造题:
		给定一棵带标号无根树,求第k小的先序遍历序列。lim:n<=5e5,k<=1e18
		solution:
		先考虑确定出发点。考虑以i为根,那么可行的序列数是所有非叶节点的儿子数的阶乘的乘积,记作f[i]
		显然这东西非常大,在n>=100的时候肯定只能从1出发
		所以我们直接暴力从小到大枚举根节点,然后跑一遍树形DP算一下可行解,就可以知道目标序列的第一个点的标号
		注意这里不能换根,因为答案太大了
		考虑现在要从根开始,我走了其中某个儿子i,那么对应的序列数量是f[rt]/sons
		那么从小到大枚举一下儿子,找到第K大序列的第二个点的标号
		类似的,我们可以一直递归做下去
		然后考虑回溯以后怎么办,把已经递归了的部分的f的贡献直接除掉,执行刚才的步骤即可
		复杂度O(n*(logV+logn)+100*100)
		详见Problem3
	
	发现的题:
		有一棵包含N个节点的二叉树,节点编号是1~N。
		现在我们知道它的中序遍历结果A1, A2, ... AN。
		问先序遍历字典序第K小的二叉树
		
	模拟赛题:
		平面内曼哈顿距离前K小距离
		
		曼哈顿距离转切比雪夫距离,发现有一个很傻的处理办法,就是直接维护出每个点在下面的情况能贡献的最小点对,可以用树套树结合二分进行调整(确实是可行的)
		考虑怎样更好写,显然树套树应该要用离线弄掉去,但这根本没法离线
		考虑二分,那么就可以用扫描线替换树套树。这里要用不unique的离散化,结合BIT即可
		然后,我们得到了第K小距离,那怎么得到最后的具体输出呢?
		考虑到第k小距离可能对应了很多点对,所以我们取其减一的值,再跑一遍二分时的check,然后将剩下的随便填上即可
		此时check的实现应该可以暴力一点,用set代替BIT
		
选数kth问题:
	tsingcheng's problem:
		从n个数中选若干(至少1)个数求和,求所有方案中第k小的和(和相同但取法不同的视为不同方案)
		lim:n<=1e5,k<=5e5
		
		solution:
		直接考虑法二,发现可以直接每次把最后一个值往后移一位,或是在最后一个值后面再加一个,那么就做完了
	P2483 k短路:
		首先考虑如何调整,可以发现必然是从最短路的末尾一段分叉,走向另一条最短路,发现这就是最短路树选非树边的过程
		看一下怎么暴力实现调整,最短路长度不太好算,考虑直接将非树边的权值重新赋一下
		那么就转化成选若干非树边,使其和第k小,这就是选数kth问题
		但注意到非树边之间有一些祖先关系,所以以此为顺序调整,可以把当前的最后一条边调整成次短边,或是直接新选一条边
		这需要我们维护后继,可以用可持久化实现,例如主席树结合二分
		特别注意,这里有重复元素,而我们要维护后继,可以用不unique的离散化实现钦定相等元素之间的顺序
	题意:给 n 个数,每次选出一个大小在 [L,R] 之间的子集,求前 k 大的子集和的和. n,k≤2×10^5.
		solution:
		从小到大排序,先考虑大小为len的集合
		调整应该是选出一段后缀向右平移一格
		多种大小分别维护即可
		结合堆实现即可
		
		类似题:CF1250I,P6646

Released under the MIT License.