题目链接https://ac.nowcoder.com/acm/problem/20259
    首先这是一道比较经典的RMQ问题,找到X和Y年间的最值来进行判断真假 ,对于区间最值问题我们可以用一颗线段树来维护,然而这只是一个小判断,比较难的是判断maybe 。如果没有想好直接打代码会调很久很久...没错,就是我,搞了两天QAQ,好了,伤心事就不提了,我们来具体看看这道题该怎么分析

    首先我们看看线段树中需要维护哪些值,左右边界必不可少,此外我们还要维护一个区间最大值sum。在判断maybe的时候还要判断区间是否连续,我们可以在线段树中维护一个cnt表示区间元素个数,对于一段查询区间x,y,我们看y-x+1是否等于查询该区间的cnt值即可
那这样我们的线段树就建立好了

   struct Node{
     int l,r;
     int sum;//维护区间最大值
     int cnt;//维护区间值的个数
 }tr[N<<2];

由于年份的数据范围太大,如果我们用map存的话,还需要离散化一下,那我们为了不离散化,可以用两个数组year,re分别存储年份和对应的降雨量,每次查询一个区间l,r时,由于输入对的数据都是递增的,我们可以先二分找出第一个不小于l的位置,和r的位置,不妨假设为st和ed,然后判断边界的年份是否相等,并查询出st+1到ed−1的最大值和区间元素数量。用两个bool变量fl,fr,来判断左右端点是否确定,因为左右端点不可能同时不确定,所以我们对左端点判断一下,if(!fl) st--;

    int st=lower_bound(year+1,year+n+1,a)-year,ed=lower_bound(year+1,year+n+1,b)-year;
        bool fl=false,fr=false;
        if(year[st]==a) fl=true;
        if(year[ed]==b) fr=true;
        if(!fl) st--;
        int op=0,cnt=0;
        if(st+1<=ed-1){
            auto res=query(1,st+1,ed-1);
            cnt=res.cnt;
            op=res.sum;
        }

接下来分类讨论
1、判断false
    当右端点年份确定,且中间年份最大降雨量大于等于右端点降雨量
    当左端点年份确定,且中间年份最大降雨量大于等于左端点降雨量
    当左右端点年份都确定,且左端点降雨量小于等于右端点降雨量
2、判断maybe
    左右端点差+1不等于查询的cnt值
    左端点不确定(因为已经排除了false的情况,所以可以直接判断,下面一样)
    右端点不确定
3、除开上面的所有情况外的结果都是true

Code:

 #include<iostream>
 #include<algorithm>
 #include<cstring>
 #include<map>
 
 #define xx first
 #define yy second
 #define debug cout<<"-----"<<endl;
 using namespace std;
 const int N=2e5+5;
 int n,m;
 int year[N],re[N];
 struct Node{
     int l,r;
     int sum;//维护区间最大值
     int cnt;//维护区间值的个数
 }tr[N<<2];
 
 inline int read() {
    int s = 0, w = 1; char ch = getchar();
    while (ch < 48 || ch > 57) { if (ch == '-') w = -1; ch = getchar(); }
    while (ch >= 48 && ch <= 57) s = (s << 1) + (s << 3) + (ch ^ 48), ch = getchar();
    return s * w;
}

 inline void pushup(Node &u,Node &l,Node &r){
     u.sum=max(l.sum,r.sum);
     u.cnt=l.cnt+r.cnt;
 }
 
 inline void pushup(int u){
     pushup(tr[u],tr[u<<1],tr[u<<1|1]);
 }
 
 inline void build(int u,int l,int r){
     tr[u].l=l,tr[u].r=r;
     if(l==r){
         tr[u].sum=re[l];
         tr[u].cnt=1;
     }
     else{
         int mid=l+r>>1;
         build(u<<1,l,mid);
         build(u<<1|1,mid+1,r);
         pushup(u);
     }
 }
 
 Node query(int u,int l,int r){
     if(tr[u].l>=l&&tr[u].r<=r) return tr[u];
     else{
         int mid=tr[u].l+tr[u].r>>1;
         if(r<=mid) return query(u<<1,l,r);
         else if(l>mid) return query(u<<1|1,l,r);
         else{
             auto left=query(u<<1,l,r);
             auto right=query(u<<1|1,l,r);
             Node res;
             pushup(res,left,right);
             return res;
         }
     }
 }
 
 int main(){
     n=read();
     for(int i=1;i<=n;i++)
        year[i]=read(),re[i]=read();
     m=read();
     build(1,1,n);
     while(m--){
         int a,b;
         a=read(),b=read();
         if(a>=b){
             puts("false");
             continue;
         }
        int st=lower_bound(year+1,year+n+1,a)-year,ed=lower_bound(year+1,year+n+1,b)-year;
        bool fl=false,fr=false;
        if(year[st]==a) fl=true;
        if(year[ed]==b) fr=true;
        if(!fl) st--;
        int op=0,cnt=0;
        if(st+1<=ed-1){
            auto res=query(1,st+1,ed-1);
            cnt=res.cnt;
            op=res.sum;
        }
         
        if((op>=re[ed]&&fr)||(re[st]<re[ed]&&fl&&fr)||(op>=re[st]&&fl)) printf("false\n");
        else if(year[ed]-year[st]+1!=cnt+2||!fr||!fl) printf("maybe\n");
        else printf("true\n");
     }
     return 0;
 }