[SCOI2007]降雨量

跨越大半年的更新

题目链接(点我)

题面描述

我们常常会说这样的话:“X 年是自 Y 年以来降雨量最多的”。它的含义是 X 年的降雨量不超过 Y 年,且对于任意 Y<Z<X,Z 年的降雨量严格小于 X 年。例如 2002,2003,2004 和 2005 年的降雨量分别为 4920,5901,2832 和 3890,则可以说“2005 年是自 2003 年以来最多的”,但不能说“2005 年是自 2002 年以来最多的”由于有些年份的降雨量未知,有的说法是可能正确也可以不正确的。

输入格式

输入仅一行包含一个正整数n,为已知的数据。以下n行每行两个整数yi和ri,为年份和降雨量,按照年份从小
到大排列,即yi<yi+1。下一行包含一个正整数m,为询问的次数。以下m行每行包含两个数Y和X,即询问“X年是
自Y年以来降雨量最多的。”这句话是必真、必假还是“有可能”。

输出格式

对于每一个询问,输出truefalse或者maybe

做法:

假设年降水量为w[i]

x,y为所求年份,l,r为其所对应的坐标,z=max(w[l+1~r-1])

由于输入的时候保证年份递增,因此没有必要离散化吧。。。

接下来就是分类讨论

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;

最大值采用线段树维护,l,r采用二分查找,详见代码:

代码:

#include<bits/stdc++.h>
#define mid (l+r)/2
using namespace std;
const int N=5e4+10;
int a[N],w[N],n;
int t[N<<2];
void build(int i,int l,int r){
    if(l==r){
        t[i]=w[l];
        return ;
    }
    build(2*i,l,mid);
    build(2*i+1,mid+1,r);
    t[i]=max(t[2*i],t[2*i+1]);
}
int query(int i,int l,int r,int L,int R){
    if(L>R) return -1e9;
    if(l>=L&&r<=R)
        return t[i];
    int ret=0;
    if(L<=mid) ret=max(ret,query(2*i,l,mid,L,R));
    if(R>mid) ret=max(ret,query(2*i+1,mid+1,r,L,R));
    return ret;
}
int main(){
    int q;
    scanf("%d",&n);
    a[0]=1e9+7,a[n+1]=-(1e9+7);
    for(int i=1;i<=n;i++)
        scanf("%d%d",&a[i],&w[i]);
    build(1,1,n);
    scanf("%d",&q);
    while(q--){
        int x,y;
        scanf("%d%d",&x,&y);
        int l=lower_bound(a+1,a+n+1,x)-a;while(a[l]<=x) l++;
        int r=lower_bound(a+1,a+n+1,y)-a;while(a[r]>=y) r--;
        int z=query(1,1,n,l,r);
        if((a[r+1]==y&&z>=w[r+1])||(a[l-1]==x&&z>=w[l-1])||(a[l-1]==x&&a[r+1]==y&&w[l-1]<w[r+1])) puts("false");
        else{
             if(r-l+1==y-x-1&&a[l-1]==x&&a[r+1]==y) puts("true");
             else puts("maybe");
        }
    }
    return 0;
}

 

 

posted @ 2020-11-19 22:53  优少  阅读(141)  评论(0编辑  收藏  举报