[学习笔记]day3-一些双指针的题

尺取法

参考博客:https://www.luogu.com.cn/blog/Nero-Yuzurizaki/chi-qu-fa-xiao-jie


http://poj.org/problem?id=3061

序列,非负,问和不小于\(S\)的最短子串的长度,双指针扫描\(O(n)\)复杂度。


https://www.luogu.com.cn/problem/P1638

类似上一题,找最短的区间使其包含\([1,m]\)的整数。


https://codeforces.com/problemset/problem/1042/D

给一个序列,询问区间和小于\(t\)的子区间个数,\(n\leq 2e5\)。

有\(s_r-s_{l-1}<t\),对于每个\(s_r\)即查询有多少个\(l\)满足\(s_{l-1}>s_r -t\),可以直接暴力地写个动态开点的值域线段树(或者对所有\(2n\)个数进行离散化写普通的线段树)。

另外这里还可以这么转化:考虑对区间进行分治,即\([l,r]\)内有多少个\(p,q(p<q):s_q-s_p<t\),不难想到这样的数对的个数来自于\([l,mid],[mid+1,r]\)的答案再加上跨越\(mid\)的区间的答案,前面两个直接递归计算,中间这一段类似归并排序。

这里稍微把\(l-1,r\)转化成了\(p,q\)以避免\(s\)排序后出现的一些问题(\(s_{l-1}\)可能会取到不正确的位置)


https://codeforces.com/problemset/problem/47/E

上古CF,大意是\((0,0)\)处有一个炮台,现在打出\(n\)个炮弹,每个炮弹速度都是\(v\),夹角\(\alpha\in(0,\frac{\pi}{4})\),有\(m\)堵垂直\(Ox\)轴的墙,询问每个炮弹最后停在那里(只要撞到墙或者地就停下来),\(n\leq 10^4,m\leq 10^5\)。

因为是很老的题,其实直接写\(O(nm)\)的暴力也卡得过去(

不过还是有些性质可以看看:利用一些高中物理知识可以很容易注意到单调性。(速度一定的情况下斜抛)

比如我们可以算出来抛物线的轨迹\(\begin{aligned}y=x\tan \alpha -\frac{g}{2v^2\cos^2\alpha}x^2\end{aligned}\),对应的零点除了\(x=0\)还有一个\(x=\frac{v^2}{g}\sin(2\alpha)\),这个东西在\(\alpha\in(0,\frac{\pi}{4})\)内是单调递增的,也就是角度越大抛得越远。

同时最高点的纵坐标也能算出是\(\begin{aligned}y_m=\frac{v^2 \sin^2 \alpha}{2g}=\frac{v^2}{4g}(1-cos(2\alpha))\end{aligned}\),也是单调的,那这题就很愉快了,对炮弹按照角度从小到大排序,对于一堵墙来说,如果角度小的能过,那么角度大的一定能过,双指针扫描炮弹和墙。

时间复杂度\(O(n\log n+m\log m)\)。

上一篇:Problem A: 小蛮腰


下一篇:【数字信号处理】基于matlab数字信号同步压缩变换【含Matlab源码 1535期】