Description
我们常常会说这样的话:“X年是自Y年以来降雨量最多的”。它的含义是X年的降雨量不超过Y年,且对于任意
Y<Z<X,Z年的降雨量严格小于X年。例如2002,2003,2004和2005年的降雨量分别为4920,5901,2832和3890,
则可以说“2005年是自2003年以来最多的”,但不能说“2005年是自2002年以来最多的”由于有些年份的降雨量未
知,有的说法是可能正确也可以不正确的。
Input
输入仅一行包含一个正整数n,为已知的数据。以下n行每行两个整数yi和ri,为年份和降雨量,按照年份从小
到大排列,即yi<yi+1。下一行包含一个正整数m,为询问的次数。以下m行每行包含两个数Y和X,即询问“X年是
自Y年以来降雨量最多的。”这句话是必真、必假还是“有可能”。
Output
对于每一个询问,输出true,false或者maybe。
Sample Input
2002 4920
2003 5901
2004 2832
2005 3890
2007 5609
2008 3024
5
2002 2005
2003 2005
2002 2007
2003 2007
2005 2008
Sample Output
true
false
maybe
false
HINT
100%的数据满足:1<=n<=50000, 1<=m<=10000, -10^9<=yi<=10^9, 1<=ri<=10^9
Source
思路
这道题,,,离散化一下年份,每次询问二分一下左右端点,查询最大值用线段树或者st表都行;
然而,判定贼恶心。。。
//我这里x,y的含义互换了,x<y ,l,r是x,y对应的数组坐标,z=max_(l+1,r-1)QUQ
if(x&&z>=x) false;
if(y&&z>=y) false;
if(x&&y),x<y false;
else
if(x&&y&&l-r+1==y-x-1) true;
else maybe;
代码实现
1 #include<cstdio> 2 const int maxn=5e4+10; 3 inline int min_(int x,int y){return x<y?x:y;} 4 inline int max_(int x,int y){return x>y?x:y;} 5 int n,m; 6 int a[maxn],b[maxn]; 7 int t[maxn<<2]; 8 int lower_bound(int k){ 9 int mid,l=1,r=n; 10 while(l<r){ 11 mid=l+r>>1; 12 if(a[mid]<k) l=mid+1; 13 else r=mid; 14 } 15 return l; 16 } 17 void build(int k,int l,int r){ 18 if(l==r){ 19 t[k]=b[l]; 20 return; 21 } 22 int mid=l+r>>1,ls=k<<1,rs=ls|1; 23 build(ls,l,mid); 24 build(rs,mid+1,r); 25 t[k]=max_(t[ls],t[rs]); 26 } 27 int search(int k,int l,int r,int al,int ar){ 28 if(al>ar) return -1e9; 29 if(l==al&&r==ar) return t[k]; 30 int mid=l+r>>1,ls=k<<1,rs=ls|1,ret=-1e9; 31 if(al<=mid) ret=max_(ret,search(ls,l,mid,al,min_(ar,mid))); 32 if(ar>mid) ret=max_(ret,search(rs,mid+1,r,max_(al,mid+1),ar)); 33 return ret; 34 } 35 int main(){ 36 scanf("%d",&n); 37 a[0]=-1e9-1,a[n+1]=1e9+1; 38 for(int i=1;i<=n;i++) scanf("%d%d",&a[i],&b[i]); 39 build(1,1,n); 40 int x,y,z,l,r; 41 scanf("%d",&m); 42 for(int i=1;i<=m;i++){ 43 scanf("%d%d",&x,&y); 44 l=lower_bound(x); 45 while(a[l]<=x) l++; 46 r=lower_bound(y); 47 while(a[r]>=y) r--; 48 z=search(1,1,n,l,r); 49 if((a[r+1]==y&&z>=b[r+1])||(a[l-1]==x&&z>=b[l-1])||(a[l-1]==x&&a[r+1]==y&&b[l-1]<b[r+1])) puts("false"); 50 else{ 51 if(r-l+1==y-x-1&&a[l-1]==x&&a[r+1]==y) puts("true"); 52 else puts("maybe"); 53 } 54 } 55 return 0; 56 }