把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

测量温度 [单调队列] 思维题

Description

某国进行了连续N(1<=N<=1000000)天的温度测量,测量存在误差,测量结果是第i天温度在[l_i,r_i]范围内。其中-10 ^ 9<l_i<=r_i<=10 ^ 9
求最长的连续的一段,满足该段内可能温度不降。

Input

第一行一个整数n。

接下来n行,每一行两个整数,表示l_i和r_i。

Output

接下来输出一个整数,表示答案。

Sample Input

6
6 10
1 5
4 8
2 5
6 8
3 5

Sample Output

4

分析

考试的时候没有考虑周到 想的是只要后面那一天有值大于等于前一天即可 也就是前后两天的温度区间第二天的右端点大于等于前一天的左端点即可

看起来没有毛病昂 只要把满足这样条件的天数连在一起就可以了

然而

我还是 too naive

可能会有这样的情况

他们是前后两天两两满足这个条件的 可是第三天却比第一天小

所以:
当前这一天的上限大于等于前面 任意一天的下限

基于此,我们要记录前面温度的下限的最大值,并每次都和当前温度上限进行比较 如果大于 由于要连续 则之前记录的最大值作废
要在后面重新找一个值来作为满足当前这一天的不降区间的起点

如果for一次去找这个当前不降区间的左端点 复杂度会爆掉
那么为了快速找到,我们可以维护一个下限单调递减的单调队列

每一次弹出队头后取值却不能取当前队头元素
队头元素前面可能还有属于当前不降区间的天数。
正确的左端点应该是上一个队头元素(它刚刚被弹出队列)的后一天
后一天不一定会在队列中 而如果后一天不满足当前下限的话 它也一定不会满足上一个下限 那么上一次他就已经有过操作

代码

#include<cstdio>
#include<deque>
using namespace std;
#define MAXN 1000005
int ans,n;
struct node{
	int l,r;
}a[MAXN];
deque<int>Q;
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
		scanf("%d %d",&a[i].l,&a[i].r);
	ans=1;
	Q.push_back(1);
	int j,tmp=0/*队头一次都没有弹出的时候*/;
	for(int i=2;i<=n;i++)
	{
		while(!Q.empty())
		{
			j=Q.front();
			if(a[i].r<a[j].l)
			{
				Q.pop_front();
				tmp=j;
			}
			else break;
		}
		ans=max(ans,i-tmp);
		while(!Q.empty())
		{
			j=Q.back();
			if(a[i].l>=a[j].l)
				Q.pop_back();//这里之前错写成了front() QAQ 
			else break;
		}
		Q.push_back(i);
	}
	printf("%d\n",ans);
	return 0;
} 

posted @   Starlight_Glimmer  阅读(12)  评论(0编辑  收藏  举报  
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
浏览器标题切换
浏览器标题切换end
点击右上角即可分享
微信分享提示