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。
用zkw线段树维护区间最大值,二分确定询问对应的区间
#include<cstdio> #include<algorithm> inline int input(){ int x=0,c=getchar(),f=1; while(c>57||c<48){if(c=='-')f=-1;c=getchar();} while(c>47&&c<58)x=x*10+c-48,c=getchar(); return x*f; } const int inf=2147483647; int n,m,M=65536; int x[50005],y[50005],mx[131072]; inline int max(int a,int b){return a>b?a:b;} inline int find(int l,int r){ int Mx=-inf; if(l<=r) for(l+=M+1,r+=M+3;l^r^1;l>>=1,r>>=1){ if(~l&1)Mx=max(Mx,mx[l^1]); if(r&1)Mx=max(Mx,mx[r^1]); } return Mx; } int main(){ n=input(); while(n*2+10<M/2)M/=2; for(int i=0;i<n;i++){ x[i]=input(); y[i]=input(); } x[n]=inf; for(int i=0;i<n;i++){ int w=i+M+2; mx[w]=y[i]; } for(int i=M-1;i;i--){ int l=i<<1,r=l^1; mx[i]=max(mx[l],mx[r]); } m=input(); while(m--){ int a=input(),b=input(); int l=std::lower_bound(x,x+n,a)-x; int r=std::upper_bound(x,x+n,b)-x-1; if(a>b)puts("false"); else if(l>r)puts("maybe"); else{ bool lk=x[l]==a,rk=x[r]==b; int Mx=find(l+lk,r-rk); if(lk&&Mx>=y[l]||rk&&Mx>=y[r]||lk&&rk&&y[l]<y[r])puts("false"); else if(r-l==b-a&&lk&&rk&&y[l]>=y[r])puts("true"); else puts("maybe"); } } return 0; }