第K大区间
定义一个区间的值为其众数出现的次数。现给出一个数列a[1…n],求将所有区间的值排序后,第K大的值为多少。区间大小为1的不计。$1≤n≤10^5$
我们首先可以发现这个玩意是有一个单调性的,就是对于一个区间$[L, R]$,如果将它向右扩展,那么这个区间的价值(也就是众数)一定是不降的。那么满足单调性我们显然可以二分,直接二分出一个答案$Ans$表示第K大值,病假设一个函数$F(X)$表示价值大于等于$X$的区间个数。则题目转化为$F(Ans) \geq K$的基础上最大化$Ans$。二分这个$X$,$F(X) \geq K$那么范围缩小到$[X, R]$,反之就缩小到$[L, X - 1]$。
基本的思路有了,接下来就剩一个求$F(X)$了。关于这个东西有一个叫做$two ~pointers$的算法可以很好地解决,简而言之就是维护两个指针$l, r$和一个表示$i$出现了几次的桶$T[i]$,从左向右扫就可以维护价值大于等于$X$的区间。
1 | r = 0 ; |
时间复杂度$O(NlogN)$
聪明的质检员
小 T 是一名质量监督员,最近负责检验一批矿产的质量。这批矿产共有 n 个矿石,从 1 到 n 逐一编号,每个矿石都有自己的重量 $w_i$ 以及价值$v_i$ 。
检验矿产的流程是:
1.给定 $m$ 个区间$[L_i,R_i]$;
2.选出一个参数 $W$;
3.对于一个区间 $[L_i,R_i ]$,计算矿石在这个区间上的检验值 $y$ :
也就是 $w$ 大于等于 $W$ 的个数和乘以价值和。
这批矿产的检验结果 $Y=∑_{i=1}^ny_i$
上头给了个标准值$S$,他希望你帮他调整参数 $W$ 的值,使 $|S-Y|$ 最小。
这个显然是要求我们二分$W$,但是如果你真的直接去二分$W$然后一个一个地计算检验的话,时间复杂度是$O(NMLogN)$显然是会炸掉的。
首先考虑单调性,我们发现当$W$变大的时候,$y$显然是会变小的,因为符合条件的矿石变少了嘛。所以$Y$也显然会跟着变小,那么$S - Y$就会变大。而至于加上绝对值,就需要分类讨论一下了。
不管这个,因为Y可以被表示成一个关于W的函数,我们设这个函数位$F(W)$,那么因为其单调不升,所以我们就可以将问题转化为求$|F(W) - S|$的最小值。而这个$F(W)$我们显然不能直接按照给的式子进行计算,我们统计对于已经确定的$W$,有贡献的$A[i]$个数的前缀和$Sum0$和$A[i]$的前缀和$Sum1$。然后计算就变成:
就变成了$O(N)$的啦,配合上二分就可以$O(NlogN)$解决啦。
数比较大,记得开$long~long$
1 |
|
跳石头
一年一度的“跳石头”比赛又要开始了!
这项比赛将在一条笔直的河道中进行,河道中分布着一些巨大岩石。组委会已经选择好了两块距离为 L 的岩石作为比赛起点和终点。在起点和终点之间,有 N 块岩石(不含起点和终点的岩石)。在比赛过程中,选手们将从起点出发,每一步跳向相邻的岩石,直至到达终点。
为了提高比赛难度,组委会计划移走一些岩石,使得选手们在比赛过程中的最短跳跃距离尽可能长。由于预算限制,组委会至多从起点和终点之间移走 M 块岩石(不能移走起点和终点的岩石)。
$0≤M≤N≤50000, 1≤L≤10^9$。
额,这时间上就是一个很纯的二分,考虑单调性,显而易见地发现移走的石头越多,那么最短跳跃的最大值就越大,额,起码不会减就是了。然后就直接枚举最短跳跃的最大值,然后从头开始判断,记录最少要移走的石头的个数与M比较一下看看是否合法就可以了。
怎么算这个最少要移走的石头的个数其实可以人类智慧法,你发现如果枚举到一个$i$与$i - 1$的距离,它是小于我们二分的值$Mid$的,那么我们把这块石头移走就可以了。这样的答案一定是最优的,好像可以用反证法来证明,但是我觉得直觉就足以告诉你最优解了,这也是为什么目前普遍认为这道题的水平并不是很高的原因。
至于怎么操作叫移去这个石头,你可以记录一下上一个石头的下标嘛。
1 |
|
借教室
我们需要处理$n$天的借教室信息,其中第 i 天学校有$ r_i $个教室可供租借。
共有$m$份订单,每份订单用三个正整数描述,分别为$d_j,s_j,t_j,$表示某租借者需要从第$s_j$天到第$t_j$天租借教室(包括第$s_j$天和第$t_j$天),每天需要租借$d_j$个教室。
借教室的原则是先到先得,也就是说我们要按照订单的先后顺序依次为每份订单分配教室。如果在分配的过程中遇到一份订单无法完全满足,则需要停止教室的分配,通知当前申请人修改订单。这里的无法满足指从第$s_j$天到第$t_j$天中有至少一天剩余的教室数量不足$d_j$个。
现在我们需要知道,是否会有订单无法完全满足。如果有,需要通知哪一个申请人修改订单。
$1≤n,m≤10^6, 0≤r_i,d_j≤10^9,1≤s_j≤t_j≤n$。
首先依然是考虑单调性,很容易发现,第$i$天肯定比$i + 1$天更容易满足需求,并且如果$i$天满足不了,那么接下来也不可能满足。单调性已有,那么考虑二分。
如何验证前 i 天是否满足条件? 由于天数已经固定了,需求也就固定了。问题转化为,有很多次离线区间加,最后要求判断每一个元素是否小于$ d $。离线区间加我们可以差分后使用前缀和的技巧来解决:设数组$s[1..n]$,对于所有区间$[l,r]$整体$+c$的操作,我们令$s[l]+=c,s[r+1]-=c$这样做完之后,我们枚举位置$i=1~n$,同时设变量add。每当访问到一个位置$i$,$add+=s[i],a[i]+=add$。这样就解决了区间加的问题。
复杂度:$O((n+m) logm)$。
1 |
|
这种做法是有可能被卡的,因此还可以用一些数据结构进行优化,但是已经超出了本题的范围,在这里不再探究。
妮厨的愤怒
对于一个字符串$S[1…n]$,询问$q$次,每次询问$[l,r]$内最长的回文串。
$1≤n ,q≤10^5,0≤l≤r<n$ ,只包含小写拉丁字母