题目链接: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;
}