单调队列:temperature
题目大意:某国进行了连续n天的温度测量,测量存在误差,测量结果是第i天温度在[l_i,r_i]范围内。
求最长的连续的一段,满足该段内可能温度不降。
第一行n
下面n行,每行l_i,r_i
1<=n<=1000000
一行,表示该段的长度
Sample Input
6
6 10
1 5
4 8
2 5
6 8
3 5
Sample Output
4
知识点:递推,单调队列
1 #include<bits/stdc++.h>
2 using namespace std;
3 queue<int> Q;
4 int l[1000005],r[1000005];
5 int q[1000005];
6 int N,t;
7 int MAX,ans,head,tail;
8 int main(){
9 //freopen("temperature.in", "r", stdin);
10 //freopen("temperature.out", "w", stdout);
11 cin>>N;
12 for(int i=1;i<=N;i++)
13 scanf("%d%d",&l[i],&r[i]);
14 /*
15 单调队列分析:
16 1.什么情况下时间断裂:当你要加入的第i天,其r[i]<l[j](前几天中的l),这个时候,
17 要先更新答案,再从把第i天卡死的离第i天最近的一天重新计数
18 2.用一个不下降单调队列来操作,有一个关键:假设某一段时间的l值为 55 53 48 37
19 36 35 34 32 29 下面一天l值为45 则此队列更新为55 53 48 45。。。因为温度45
20 的天数靠后而且l值高,若这一天可以,则前六天一定可以,所以使队列元素为55 53 48 45.
21 但这样还不行,无法确定天数信息,所以让q[]保存天
22 数,利用l[q[head]]来调用,更新q就是更新l数组,反正是
23 O(n)地从前向后扫一遍,不影响答案
24 */
25 head=1;tail=0;
26 for(int i=1;i<=N;i++){
27 while(l[q[head]]>r[i]&&head<=tail) //q是单调减队列,如果当前的l[q[head]]>r[i]
28 head++; //则这一天不能从第q[head]天接上 因此继续向后
29 //找,直到l[q[head]]<r[i],由于是单调队列,所以
30 //后面几天一定可以
31
32 if(head<=tail)//更新ans
33 ans=max(ans,i-q[head]+1);
34
35 int t=i;
36 while(l[i]>l[q[tail]]&&head<=tail)
37 t=q[tail],tail--;
38 l[t]=l[i];
39 q[++tail]=t;
40 }
41 cout<<ans;
42 return 0;
43 }
44