[POI 2011]Temperature(单调队列)

题目链接

http://main.edu.pl/en/archive/oi/18/tem

题目大意

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

思路

显然,一个合法的区间是保证 li 不增,并且区间左端点的 r 小于等于区间右端点的 r 。因为显然温度的线段尽量贴着每天的L边界才能尽可能满足条件。假如我们维护完之前的一段时间,然后现在要加入第 i 天,若 Li1>Ri ,则显然无法加入第 i 天,

假如我们现在已经知道连续的一段 [i,j1] 是合法的,那么 [i,j] 合法,当且仅当

maxitj1{Lt}Rj

因为显然温度的线段尽量贴着每天的L边界才能尽可能满足条件,那么到了第 j1 天时的温度显然为 maxitj1{Lt} ,若 maxitj1{Lt}>Rj ,那么无论如何都无法使得 [i,j] 合法了。

一种比较显然的做法就是

这样一来,我们可以从1到第n天扫整个区间序列,并维护一个 L 非增的单调队列,这样队首的元素的 L 值就是当前的合法区间里最大的那个 L 。假如当前扫到了第 i 天,就要在第 i 天入队后,维护队首,使得队首的 L 小于等于第 i 天的 R ,而 q[head1] 是不满足 L 小于等于第 i 天的 R 这个条件的,则当前 [q[head1]+1,i] 这段区间就是一个合法区间,并且是所有的 [k,i] 区间里最大的区间。就用 iq[head1] 来更新答案。

代码

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>

#define MAXN 2100000

using namespace std;

int L[MAXN],R[MAXN],n;
int q[MAXN],h=1,t=1,maxans=0;

int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d%d",&L[i],&R[i]);
    q[t++]=1;
    maxans=max(maxans,t-h);
    for(int i=2;i<=n;i++)
    {
        while(h<t&&L[q[t-1]]<L[i]) t--;
        q[t++]=i;
        while(h<t&&L[q[h]]>R[i]) h++;
        maxans=max(maxans,i-q[h-1]);
    }
    printf("%d\n",maxans);
    return 0;
}

你可能感兴趣的:([POI 2011]Temperature(单调队列))