2276: [Poi2011]Temperature
Time Limit: 20 Sec Memory Limit: 32 MBSubmit: 731 Solved: 334
[Submit][Status][Discuss]
Description
The Byteotian Institute of Meteorology (BIM) measures the air temperature daily. The measurement is done automatically, and its result immediately printed. Unfortunately, the ink in the printer has long dried out... The employees of BIM however realised the fact only recently, when the Byteotian Organisation for Meteorology (BOM) requested access to that data.
An eager intern by the name of Byteasar saved the day, as he systematically noted down the temperatures reported by two domestic alcohol thermometers placed on the north and south outside wall of the BIM building. It was established decades ago by various BIM employees that the temperature reported by the thermometer on the south wall of the building is never lower than the actual temperature, while that reported by the thermometer on the north wall of the building is never higher than the actual temperature. Thus even though the exact temperatures for each day remain somewhat of a mystery, the range they were in is known at least.
Fortunately for everyone involved (except Byteasar and you, perhaps), BOM does not require exact temperatures. They only want to know the longest period in which the temperature was not dropping (i.e. on each successive day it was no smaller than on the day before). In fact, the veteran head of BIM knows very well that BOM would like this period as long as possible. To whitewash the negligence he insists that Byteasar determines, based on his valuable notes, the longest period in which the temperature could have been not dropping. Now this is a task that Byteasar did not quite expect on his BIM internship, and he honestly has no idea how to tackle it. He asks you for help in writing a program that determines the longest such period.
某国进行了连续n天的温度测量,测量存在误差,测量结果是第i天温度在[l_i,r_i]范围内。
求最长的连续的一段,满足该段内可能温度不降。
Input
In the first line of the standard input there is one integer n(1<=N<=1000000) that denotes the number of days for which Byteasar took notes on the temperature. The measurements from day are given in the line no.i+1 Each of those lines holds two integers, x and y (-10^9<=x<=y<=10^9). These denote, respectively, the minimum and maximum possible temperature on that particular day, as reported by the two thermometers.
In some of the tests, worth 50 points in total, the temperatures never drop below -50 degrees (Celsius, in case you wonder!) and never exceeds 50 degrees (-50<=x<=y<=50)
第一行n
下面n行,每行l_i,r_i
1<=n<=1000000
Output
In the first and only line of the standard output your program should print a single integer, namely the maximum number of days for which the temperature in Byteotia could have been not dropping.
一行,表示该段的长度
Sample Input
6 10
1 5
4 8
2 5
6 8
3 5
Sample Output
HINT
Source
Analysis
一道思考题
显然这道题有点SRM的熟悉的感觉(以前做过?)
不过记忆不是很清晰不是很敢确定(而且我那时没有记比赛的习惯)
那么首先画个像温度计一样的图
有点像Flappy Bird
如果把上下界分离的话,令人联想到USACO 银组的乱发节
(因为如果这一天之后的温度下界没有这一天的高的话,答案是没有影响的)
= =
解法单调队列
维护队列内的每一天的温度下界单调递减
因为对于待进队元素 i ,如果他的温度下界 ≥ 队首元素的温度下界的话, i 就显然可以继承队首元素的答案,那么他的答案就是队首元素 +1
这样队列的温度下界会成一个递减状
但是进队元素的下界不一定仅仅是高于队首元素,也有可能高于队首至队列中间的一大段元素
所以 i 可以继承的应该是最后一个矮于它的元素的答案
那么 ans[ i ] = ans[ que[head] ] + i - que[ head ] -1
然后一个while解决问题
为什么有个-1被标成了红色:我个人觉得那个-1是不需要加的,但是在后期的Debug中发现不加不行
= =还是太弱啊
那么到后面结束遍历后,需要再处理一下队内
这个时候队内的元素都是可以直接持续到第 n 天的,直接处理就好
至于这个解法的更多问题,都可以用单调队列的性质解决
Code
1 #include<cstdio> 2 #include<iostream> 3 #define maxn 1000100 4 using namespace std; 5 6 int n,minh[maxn],maxh[maxn],ans[maxn]; 7 int que[maxn],head,tail; 8 9 int main(){ 10 scanf("%d",&n); 11 12 for(int i = 1;i <= n;i++){ 13 scanf("%d%d",&minh[i],&maxh[i]); 14 ans[i] = 1; 15 } 16 17 for(int i = 1;i <= n;i++){ 18 while(tail < head && minh[que[tail+1]] > maxh[i]) 19 ans[que[tail+1]] += i-que[tail+1]-1, 20 tail++; 21 while(tail < head && minh[que[head]] <= minh[i]) 22 ans[i] = ans[que[head]]+i-que[head], 23 head--; 24 que[++head] = i; 25 26 // for(int i = tail+1;i <= head;i++) 27 // printf("%d ",que[i]);cout << endl; 28 // for(int i = 1;i <= n;i++) 29 // printf("%d ",ans[i]);cout << endl; 30 // 31 } 32 33 while(tail < head) 34 ans[que[tail+1]] += n-que[tail+1], 35 tail++; 36 37 // for(int i = 1;i <= n;i++){ 38 // printf("%d ",ans[i]); 39 // } 40 // 41 int ret = 1; 42 for(int i = 1;i <= n;i++) 43 ret = max(ret,ans[i]); 44 printf("%d",ret); 45 46 return 0; 47 }