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

 

posted @ 2015-07-07 11:52  CXCXCXC  阅读(281)  评论(0编辑  收藏  举报