【RMQ+二分】poj 2637 WorstWeather Ever

http://poj.org/problem?id=2637

二分查找到对应区间,然后根据逻辑判断进行RMQ求取区间最值判断输出,题意搞懂是关键。

/*
  poj 2637 RMQ + 二分
题意:
   给你多组year,rainfall
   多组查询,Y、X,查询[Y,X]区间是否满足Y是最大降雨量的要求
   (1)降雨量X>=Y
   (2)[Y-1,X-1]降雨量都已知且严格小于X
   (3)X、Y降雨量已知
   满足的输出true,不满足输出false,可能满足的输出maybe
思路:
   之前的都是直接告诉你区间下标,这道题需要自己找,二分查找lower_bound>=key的元素
   然后分情况讨论,不同情况下RMQ()的区间还有区别呦,这里WA过
   注意RMQ()中L>R的情况,返回的值尽可能的小<-10^9(因为找的是区间最大值)
   至于怎么分情况需要读者好好想想,看上去很复杂,仔细理解下还是很easy滴~
*/
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<vector>
#include<set>
#include<map>
#include<algorithm>
#include<sstream>
#define eps 1e-9
#define pi acos(-1)
#define INF 0x7fffffff
#define inf -INF
#define long long ll
#define M 10
#define N 1010
using namespace std;
const int _max = 5e4 + 10;

int d[_max][20],a[_max],b[_max];

int n,Q;

void RMQ_init(){
  for(int i = 0; i < n; ++ i) d[i][0] = b[i];//降雨量
  for(int j = 1;(1<<j)<=n;++ j)
  for(int i = 0;i + (1<<j)-1 < n;++ i){
     d[i][j] = max(d[i][j-1],d[i+(1<<(j-1))][j-1]);
  }
}

int RMQ(int L,int R){
  if(L>R) return inf;//最小值<-10^9
  int k = 0;
  while((1<<(k+1))<= R-L+1)++k;
  return max(d[L][k],d[R-(1<<k)+1][k]);
}

int main()
{
   #ifndef ONLINE_JUDGE
   freopen("input.txt","r",stdin);
   #endif // ONLINE_JUDGE
   int cnt = 0;
   while(scanf("%d",&n)==1){
   // memset(a,inf,sizeof(a));
    for(int i = 0; i < n; ++ i) scanf("%d%d",a+i,b+i);//默认已排序
    scanf("%d",&Q);if(Q+n==0) break;
    if(cnt) puts("");else cnt++;
    int Y,X;
    RMQ_init();
    while(Q--){
        scanf("%d%d",&Y,&X);
        int l = lower_bound(a,a+n,Y)-a;
        int r = lower_bound(a,a+n,X)-a;
        int t;
        if(a[l]!=Y&&a[r]!=X) puts("maybe");//Y.X均未知
        else if(a[l]==Y&&a[r]==X){//Y.X均已知
            if(b[l] < b[r]) puts("false");
            else{
                t = RMQ(l+1,r-1);
                if(t < b[r]){
                    if(r-l+1==X-Y+1) puts("true");
                    else puts("maybe");
                }
                else puts("false");
            }
        }
        else if(a[l]==Y&&a[r]!=X){
          t = RMQ(l+1,r-1);
          if(t>=b[l]) puts("false");
          else puts("maybe");
        }
        else{
           t = RMQ(l,r-1);
           if(t>=b[r]) puts("false");
           else puts("maybe");
        }
    }
   }
   return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值