题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2276
发现一段合法的充要条件是对于任意位置,前面的 l 的最大值小于等于自己的 r 。
因为是找前一段的 l 最大值,所以按 l 递减建一个单调队列即可。新加一个点时把队首大于自己 r 的弹栈。
不是从 q[ hd ] 到 i ,而是从 q[ hd-1 ]+1 到 i 。因为 q[ hd-1 ] 到 q[ hd ] 之间的值小于 q[ hd ],若 q[ hd ]合法,则它们也合法。
因为不合法的都被弹了,单调队列里的元素所以是在能让上一个元素合法的基础上的,所以可以选。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N=1e6+5; int n,l[N],r[N],q[N],hd,tl,ans; int main() { scanf("%d",&n); for(int i=1;i<=n;i++)scanf("%d%d",&l[i],&r[i]); hd=1;q[tl=1]=1;ans=1; for(int i=2;i<=n;i++) { while(l[q[hd]]>r[i]&&hd<=tl)hd++; ans=max(ans,i-(q[hd-1]+1)+1); while(l[q[tl]]<l[i]&&hd<=tl)tl--; q[++tl]=i; } printf("%d\n",ans); return 0; }