单调队列: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  
时间: 2024-10-08 17:16:46

单调队列:temperature的相关文章

bzoj2276: [Poi2011]Temperature(单调队列/堆)

这题有两种写法,而且是完全(几乎?)不一样的写法...并不是换了个方法来维护而已 单调队列O(N):用一个队列维护a[]的单调递减,对于每个i满足a[队头]<=b[i],然后就可以算出以每一位为结尾的最大答案了 #include<stdio.h> #include<cstring> #include<iostream> #include<cstdlib> using namespace std; const int maxn=1000010,inf=1

BZOJ 2276 Poi2011 Temperature 单调队列

题目大意:给定一个序列,每个元素的大小有一个取值范围,求一段区间满足区间内元素可能单调不降 对L维护一个单调不增的单调队列,一旦新插入的R值比队头的L值小就把队头弹掉 这样可以保证单调队列中的元素是合法的极大子区间 然后更新答案就行了 乱写读入优化害死人啊QwQ #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define M 1001001 usi

【动态规划】【单调队列】tyvj1305 最大子序和

http://blog.csdn.net/oiljt12138/article/details/51174560 单调队列优化dp #include<cstdio> #include<deque> #include<algorithm> #include<iostream> using namespace std; typedef long long ll; int n,m; ll a[300100],ans; deque<int>q; int

hdu_5884_Sort(二分+单调队列)

题目链接:hdu_5884_Sort 题意: 有n个数,每个数有个值,现在你可以选择每次K个数合并,合并的消耗为这K个数的权值和,问在合并为只有1个数的时候,总消耗不超过T的情况下,最小的K是多少 题解: 首先要选满足条件的最小K,肯定会想到二分. 然后是如何来写这个check函数的问题 我们要贪心做到使消耗最小,首先我们将所有的数排序 然后对于每次的check的mid都取最小的mid个数来合并,然后把新产生的数扔进优先队列,直到最后只剩一个数. 不过这样的做法是n*(logn)2 ,常数写的小

[Vijos 1243]生产产品(单调队列优化Dp)

Description 在经过一段时间的经营后,dd_engi的OI商店不满足于从别的供货商那里购买产品放上货架,而要开始自己生产产品了!产品的生产需要M个步骤,每一个步骤都可以在N台机器中的任何一台完成,但生产的步骤必须严格按顺序执行.由于这N台机器的性能不同,它们完成每一个步骤的所需时间也不同.机器i完成第j个步骤的时间为T[i,j].把半成品从一台机器上搬到另一台机器上也需要一定的时间K.同时,为了保证安全和产品的质量,每台机器最多只能连续完成产品的L个步骤.也就是说,如果有一台机器连续完

单调队列

先放上luogu的题目链接--滑稽窗口 然后我们再来讲单调队列 单调队列是指这样一种队列:在队列中的元素为单调递增状态或单调递减状态. 例如1 2 3 4 5和9 2 1都是单调队列,但1 2 2 3 4和4 3 4 5就不是单调队列. 但普通队列明显是维持不了单调队列的性质的. 为了维持单调队列的单调性质,我们只好想一些方法.方法就是修改队列的性质.单调队列不仅队头可以出队,队尾也可以出队. 比如说有一个单调队列是 1 3 7 8 现在突然要从队尾进来一个6如果单纯的把6插进队尾的话,那这个队

单调队列 BZOJ 2096 [Poi2010]Pilots

2096: [Poi2010]Pilots Time Limit: 30 Sec  Memory Limit: 162 MBSubmit: 819  Solved: 418[Submit][Status][Discuss] Description Tz又耍畸形了!!他要当飞行员,他拿到了一个飞行员测试难度序列,他设定了一个难度差的最大值,在序列中他想找到一个最长的子串,任意两个难度差不会超过他设定的最大值.耍畸形一个人是不行的,于是他找到了你. Input 输入:第一行两个有空格隔开的整数k(0

HDU 3706 Second My Problem First (单调队列)

题意:求给定的一个序列中最长子序列,该子序列的最大值和最小值介于m和k之间. 析:用两个单调队列来维护一个最小值,一个最大值,然后每次更新即可. 代码如下; #pragma comment(linker, "/STACK:1024000000,1024000000") #include <cstdio> #include <string> #include <cstdlib> #include <cmath> #include <i

codevs3327选择数字(单调队列优化)

3327 选择数字 时间限制: 1 s 空间限制: 256000 KB 题目等级 : 钻石 Diamond 题目描述 Description 给定一行n个非负整数a[1]..a[n].现在你可以选择其中若干个数,但不能有超过k个连续的数字被选择.你的任务是使得选出的数字的和最大. 输入描述 Input Description 第一行两个整数n,k 以下n行,每行一个整数表示a[i]. 输出描述 Output Description 输出一个值表示答案. 样例输入 Sample Input 5 2