BZOJ 1067:[SCOI2007]降雨量(RMQ+思维)
http://www.lydsy.com/JudgeOnline/problem.php?id=1067
题意:……
思路:首先我们开一个数组记录年份,一个记录降雨量,因为年份是按升序排列的,所以我们在每个询问找下标的时候可以二分搜索,然后对于每个询问我们是要寻找区间的最大值,因此我们可以使用ST表来做。比较麻烦的是判断三种答案的情况,做了一个下午。假设询问输入的是X和Y(X < Y)接下来分为四种情况:
1、X是已知,Y是已知。那么这是最容易想到的情况。
1-1、如果在[X+1,Y-1]区间中存在大于等于Y的降雨量,或者Y的降雨量大于X的降雨量,那么就输出false。
1-2、否则如果[X+1,Y-1]中存在未知年份,那么就输出maybe。
1-3、否则输出true。
2、X是已知,Y是未知。
2-1、如果在[X+1,Y]区间中存在大于等于X的降雨量,那么输出false。
2-2、否则输出maybe。
这里要注意如果X+1 > Y的情况,那么肯定是输出maybe的。要特判一下。(坑了好久)
3、X是未知,Y是已知。
3-1、如果在[X,Y-1]区间中存在大于等于Y的降雨量,那么输出false。
3-2、否则输出maybe。
4、X是未知,Y是未知。
4-1、直接输出maybe。
这里lower_bound()返回的是大于等于x的下标,upper_bound() - 1返回的是小于等于x的下标。
判断存在不存在就直接是二分后的下标和本身是不是相等的,而不用用到map这样的数据结构判断。
1 #include <cstdio> 2 #include <cstring> 3 #include <cmath> 4 #include <algorithm> 5 #include <iostream> 6 using namespace std; 7 #define N 50010 8 #define INF 0x3f3f3f3f 9 10 int n, year[N], fall[N], dp[N][30]; 11 12 void RMQ_Init() { 13 for(int i = 1; i <= n; i++) dp[i][0] = fall[i]; 14 int ed = (int)(log(n) / log(2.0)); 15 for(int j = 1; j <= ed; j++) 16 for(int i = 1; i + (1 << j) - 1 <= n; i++) 17 dp[i][j] = max(dp[i][j-1], dp[i+(1<<(j-1))][j-1]); 18 } 19 20 int RMQ_Query(int l, int r) { 21 if(l > r) return -INF; // !!!!! 22 int ed = (int)(log(r - l + 1.0) / log(2.0)); 23 return max(dp[l][ed], dp[r-(1<<ed)+1][ed]); 24 } 25 26 int main() { 27 int q; 28 while(~scanf("%d", &n)) { 29 for(int i = 1; i <= n; i++) scanf("%d%d", &year[i], &fall[i]); 30 RMQ_Init(); 31 scanf("%d", &q); 32 while(q--) { 33 int l, r; scanf("%d%d", &l, &r); 34 if(l > r) { puts("false"); continue; } 35 int lid = lower_bound(year + 1, year + 1 + n, l) - year; 36 int rid = upper_bound(year + 1, year + 1 + n, r) - year - 1; 37 int ans, res; 38 if(year[lid] != l) { 39 ans = RMQ_Query(lid, rid - 1); 40 if(year[rid] != r) puts("maybe"); 41 else if(ans >= fall[rid]) puts("false"); 42 else puts("maybe"); 43 } else if(year[rid] != r) { 44 ans = RMQ_Query(lid + 1, rid); 45 if(ans >= fall[lid]) puts("false"); 46 else puts("maybe"); 47 } else { 48 ans = RMQ_Query(lid + 1, rid - 1); 49 if(fall[rid] <= ans || fall[lid] < fall[rid]) puts("false"); 50 else if(rid - lid != year[rid] - year[lid]) puts("maybe"); 51 else puts("true"); 52 } 53 } 54 } 55 return 0; 56 } 57 58 /* 59 2 60 2000 4000 61 2005 4500 62 1 63 2005 2010 64 65 maybe 66 */