单调队列: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  

 

你可能感兴趣的:(队列)