前言
以前学过,但是学炸了,现在来重温一下(说不定以后以后也会这样写。。。)
大概思路
如果对于一个问题我们可以二分,而且它有很多组,组与组之间没有影响,我们就可以整体二分。整体二分就是二分一个值,然后将合法和不合法的再分治解决。很简单吧
题目
( exttt{The 1st})
题目大意
给定 (n) 个整数构成的序列 (a_{1,2,...,n}),将对于指定的闭区间 ([l,r]) 查询其区间内的第 (k) 小值。
思路
作为主席树的模板题我们肯定不可以用主席树做.jpg
我们发现这个答案显然可以二分,而我们统计一个数在一个区间内的排名可以用树状数组实现。
于是我们就可以在(Theta(mlog^2 n))的时间复杂度内解决这个问题。然而还是跑不过主席树的(Theta(mlog n))。。。
( exttt{Code})
( exttt{The 2ed})
题目大意
给出一个长度为(n)的数列(a_{1,2,...,n}),有(m,)次操作,分别为以下两种:
-
给出(x,y),将(a_x)更改为(y)
-
给出(l,r,k),求出区间([l,r])中第(k)大的数
(n,mle 10^5)
思路
这道题就充分体现了整体二分如何吊打树套树。
这道题有修改操作,其实我们在树状数组计算贡献的时候把原先的值变负就可以了。
这里提一下,我们这样做是对了是因为我们整体二分对于一个查询可以只考虑在此之前的操作,具体见代码,当时就是这里没有( exttt{get})到。
( exttt{Code})
对比
( exttt{The 3rd})
题目大意
有(n)个可重集,(m)次操作,每次操作为以下两种:
-
给出(l,r,c),在([l,r])这些可重集里加入元素(c)
-
给出(l,r,k),求([l,r])这些可重集的并集的第(k)大元素
思路
如果你真的懂整体二分的话,这个题就是水题,直接用线段树实现区间加减以及区间求和即可。
不过用树状数组实现的话常数会小一点。
( exttt{Code})
对比
树套树:
整体二分:
( exttt{The 4th})
题目大意
给出一个(n imes n)的(01)表格,有(m)次查询,给出两个格子(A,B),求出以(A)为重心的正方形的最大边长使得该正方形可以走到(B)(中心走到(B))。
思路
我们发现我们对于一次查询可以直接二分+( exttt{BFS})解决,于是按照该思路整体二分即可。
时间复杂度是(Theta(n^3))的,但是不吸氧还是可以卡过去,充分体现了整体二分的常数之小。
( exttt{Code})
代码里面最后二分出来的(l),其实是不满足的最小值。注意一下就好了。