单调队列感觉还是用的不熟练, 这几天再找几个题做做,顺便再练一练斜率优化.
练习1. Luogu P3522 [POI2011]TEM-Temperature
大意: n个数, 第$i$个数可以替换为$[L_i,R_i]$中的任意一个, 求最长连续非降序列的长度
考虑贪心, 每次选择尽量小的数, 对于第$i$个数, 如果$R_i$小于上次选择的数, 发现这里取什么贪心就不能判断了, 所以就要用单调队列辣.
其实就是枚举右端点, 单队求出最小的左端点值.
假设现在维护的区间为$[l,r]$, 新添加一个点$r+1$, 假设$[l,r]$中存在一点$x$, 并且$L_x>R_{r+1}$的话, 那么区间$[l,x]$的点都要删除, 也就是说要找到最大的$x$满足$L_x>R_{r+1}$, 所以维护一个关于L的递减的单队即可.
#include <iostream> #include <algorithm> #include <math.h> #include <cstdio> #include <set> #include <queue> #define REP(i,a,n) for(int i=a;i<=n;++i) using namespace std; const int N = 1e6+10; int n; int L[N], R[N]; int main() { scanf("%d", &n); REP(i,1,n) scanf("%d%d",L+i,R+i); deque<int> q; int ans = 0, pos = 1; REP(i,1,n) { while (q.size()&&L[q.front()]>R[i]) pos = q.front()+1, q.pop_front(); ans = max(ans, i-pos+1); while (q.size()&&L[q.back()]<=L[i]) q.pop_back(); q.push_back(i); } printf("%d\n", ans); }