P3522 [POI2011]TEM-Temperature(单调队列)

题目描述

某国进行了连续 n( 1≤n≤1,000,000)天的温度测量,测量存在误差,测量结果是第 ii 天温度在 [li,ri] 范围内。
求最长的连续的一段,满足该段内可能温度不降。

输入格式

In the first line of the standard input there is one integer n n ( 1 \le n \le 1,000,000 1≤n≤1,000,000) that denotes the number of days for which Byteasar took notes on the temperature. The measurements from day are given in the {(i + 1)}(i+1)-th line . Each of those lines holds two integers, x x and y y ( −109≤x≤y≤109 ). These denote, respectively, the minimum and maximum possible temperature on that particular day, as reported by the two thermometers.
In some of the tests, worth 50 points in total, the temperatures never drop below -50 −50 degrees (Celsius, in case you wonder!) and never exceeds 50 50 degrees ( −50≤x≤y≤50).

输出格式

In the first and only line of the standard output your program should print a single integer, namely the maximum number of days for which the temperature in Byteotia could have been not dropping.

输入输出样例

输入
6
6 10
1 5
4 8
2 5
6 8
3 5
输出
4

题目分析

通过分析题目我们可以发现:只有这一段序列每天的最高温度大于这一天以前每天的最低温度,才能满足序列不下降

只要发现了这一点,后面就好办了。
我们可以用单调队列维护一段序列中l[i]的最大值,每次放入i时,先将序列中温度最小值大于 r[i] 的点弹出。
于是以i为结尾的最大合法解即为:i-l[q[head]-1] //q[head-1]到q[i]之间的非极值的点也是可以放入序列中作为合法解的一部分的。

代码如下
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <set>
#include <map>
#include <queue>
#include <vector>
#include <algorithm>
#include <iomanip>
#define LL long long
#define ULL unsigned long long
#define PII pair<int,int>
#define PLL pair<LL,LL>
#define PDD pair<double,double>
#define x first
#define y second
using namespace std;
const int N=1e6+5,INF=1e9;
int l[N],r[N],q[N];
int main()
{
	cin.tie(0);
	ios::sync_with_stdio(false);
	int n;
	cin>>n;
	for(int i=1;i<=n;i++) cin>>l[i]>>r[i];
	int ans=1;					//答案的最小值就是1
	int head=0,tail=-1;
	for(int i=1;i<=n;i++)
	{
		while(head<=tail&&l[q[head]]>r[i]) head++;		//将序列中温度最小值大于 r[i] 的点弹出
		if(head<=tail) ans=max(ans,i-q[head-1]);		//记录以i为结尾的最长合法序列
		while(head<=tail&&l[q[tail]]<l[i]) tail--;		//将l[i]放入单调队列中
		q[++tail]=i;
	}
	cout<<ans<<endl;
	return 0;
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lwz_159

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值