• Evanyou Blog 彩带


      题目传送门

    降雨量

    题目背景

    07四川省选

    题目描述

    我们常常会说这样的话:“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年以来降雨量最多的。”这句话是必真、必假还是“有可能”。

     

    输出格式:

     

    对于每一个询问,输出true,false或者maybe。

     

    输入输出样例

    输入样例#1: 
    6
    2002 4920
    2003 5901
    2004 2832
    2005 3890
    2007 5609
    2008 3024
    5
    2002 2005
    2003 2005
    2002 2007
    2003 2007
    2005 2008
    
    输出样例#1: 
    false
    true
    false
    maybe
    false
    

    说明

    100%的数据满足:1<=n<=50000, 1<=m<=10000, $-10^9leq yileq 10^9$,$1leq rileq 10^9$


      分析:

      一道细节贼多的$RMQ$问题。

      因为年份太多,所以不能直接用年份作下标,需要离散化。每次询问给定左端点和右端点后,找出第一个不小于它们的年份,也就确定了下标,令它们为$sta,ed$。那么在区间$(sta,ed)$中找到最大的降雨量,与边界进行判断得到结果。当然,如果左端点并没有在输入的年份中,就应该要在区间$[sta,ed)$中找最大的降雨量判断。判断的情况如下:

      $false$:

      右端点与左端点都已经在输入中给出且右端点的降雨量大于左端点降雨量;

      右端点的年份已经在输入中给出且在区间中找到的最大值大于等于右端点降雨量;

      左端点的年份已经在输入中给出且在区间中找到的最大值大于等于左端点降雨量;

      $maybe$:

      左端点或右端点没有在输入数据中给出; 

      左右端点的下标之差小于左右端点的年份之差;

      $true$:

      除了以上情况。

      只要注意好所有的细节,考虑到所有的情况,这题也就不难想了。

      Code:

      

    //It is made by HolseLee on 4th Sep 2018
    //Luogu.org P2471
    #include<bits/stdc++.h>
    using namespace std;
    
    const int N=5e4+7;
    int n,m,ye[N],ra[N];
    
    namespace Segment {
        int seg[N<<2];
    
        inline void pushup(int rt)
        {
            seg[rt]=max(seg[rt<<1],seg[rt<<1|1]);
        }
        
        void build(int l,int r,int rt) 
        {
            if( l>r )return;
            if( l==r ) {
                seg[rt]=ra[l]; return;
            }
            int mid=(l+r)>>1;
            build(l,mid,rt<<1); build(mid+1,r,rt<<1|1);
            pushup(rt);
        }
    
        int quary(int l,int r,int rt,int L,int R)
        {
            int ret=0;
            if( l>R || r<L ) return ret;
            if( L<=l && r<=R ) return seg[rt];
            int mid=(l+r)>>1;
            if( L<=mid ) ret=max(ret,quary(l,mid,rt<<1,L,R));
            if( R>mid ) ret=max(ret,quary(mid+1,r,rt<<1|1,L,R));
            return ret;
        }
    }
    
    inline int read()
    {
        char ch=getchar(); int num=0; bool flag=false;
        while( ch<'0' || ch>'9' ) {
            if( ch=='-' ) flag=true;
            ch=getchar();
        }
        while( ch>='0' && ch<='9' ) {
            num=(num<<1)+(num<<3)+(ch^48);
            ch=getchar();
        }
        return flag ? -num : num;
    }
    
    int main()
    {
        n=read();
        for(int i=1; i<=n; ++i) {
            ye[i]=read(), ra[i]=read();
        }
        Segment::build(1,n,1);
        m=read();
        int x,y,sta,ed,ka; bool fl,fr;
        for(int i=1; i<=m; ++i) {
            x=read(); y=read();
            if( x>=y ) {
                printf("false
    "); continue;
            }
            sta=lower_bound(ye+1,ye+n+1,x)-ye;
            ed=lower_bound(ye+1,ye+n+1,y)-ye;
            fl=ye[sta]==x, fr=ye[ed]==y; ka=0;
            if( !fl ) sta--;
            if( sta+1<=ed-1) ka=Segment::quary(1,n,1,sta+1,ed-1);
            if( (ka>=ra[sta] && fl) || (ka>=ra[ed] && fr) || (ra[ed]>ra[sta] && fl && fr) ) printf("false
    ");
            else if( ed-sta!=ye[ed]-ye[sta] || !fl || !fr ) printf("maybe
    ");
            else printf("true
    ");
        }
    }
  • 相关阅读:
    java中JSON转换
    使用Admin监控
    linux安装tomcat
    SpringBoot整合Redis
    linux6.8安装docker
    使用Actuator监控
    SpringBoot集成阿里巴巴Druid监控
    使用Log4j日志处理
    SpringBoot多数据源
    SpringBoot文件上传下载
  • 原文地址:https://www.cnblogs.com/cytus/p/9582995.html
Copyright © 2020-2023  润新知