• 降雨量(附我的SB调题过程)


    题目描述

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

    输入格式

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

    输出格式

    对于每一个询问,输出 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%100\%100% 的数据, 1≤n≤50000,1≤m≤10000,−109≤yi≤109,1≤ri≤109 1 le n le 50000, 1 le m le 10000, -10^9 le y_i le 10^9, 1 le r_i le 10^91n50000,1m10000,109​​yi​​109​​,1ri​​109​​


    这是一段扯淡,不想看的直接往下翻

    这是Lv神考试的T2,考场上只知道写一个St表,但是数据范围看错了,下标直接用了年份,里面的判断也写得狗屁不通,然后被卡爆了。

    靠后本着一定要学会的精神开始调,看了个超短的题解,学会了怎么用lower_bound,然后瞎搞一波就能过,然后就开开心心的写了一发

    ……

    然后就成功的WA了三个点,RE了七个点,调了一下午也没调出来(一起的学弟昨天就切了)

    厚着脸皮去问了他们,被告知了一个一样的方法,然后心态就很爆炸

    可能是他们的思想太过高深,我太菜了,见着自己的新思路重写了一个

    下了数据后跑了发对拍,发现错的乱七八糟的

    然后用了二十分钟重构了代码,对着数据和标程拍了一会儿

    过了五个点,还是最大的数据,心想应该是小数据hack了

    时间已经过了一个下午,去食堂随便吃了顿饭(还和大佬打了快乐篮球)

    回来继续调,加了一个判断条件,六十分,然后找了F姓dalao帮忙,

    大佬一口咬定是我写的太丑了(我也是这么想的QAQ)

    然后dalao在期间郑重向我表明我的某行代码不是错的,

    经过了半个小时的懵逼,我们把刚才说的那行代码改了,然后就A了,后来才知道是出现了重复状态

    dalao已经在豆腐上撞死了,我发现自己被安排的明明白白的。


    下面是正经的题解
    我们发现这道题如果没有maybe这个状态就是个St表的裸题,然后只要判断是否正确,
    但是加了之后我们也不用慌,只需要分讨论
    我们已知true只有一种判断方法,那就是前后两个段点存在,中间没有不存在的点,中间所有点的值严格小于后面的点的值,后端点<=前端点
    而maybe的可能性就比较多了
            (1)当前后两个都没有时
            (2)当前面有,后面没有
            (3)后面有,前面没有
            (4)前后都有,但是中间有空缺
    而false只用在开头判断后端点的年份是否严格大于前端点,其余的在最后输出就可以了(因为已经判断完了false的)
    下面给出代码:
    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<string>
    #include<cmath>
    #include<queue>
    using namespace std;
    inline int rd()
    {
        int x=0,f=1;
        char ch=getchar();
        for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-1;
        for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';
        return x*f;
    }
    void write(int x)
    {
        if(x<0) putchar('-'),x=-x;
        if(x>9) write(x/10);
        putchar(x%10+'0');
        return ;
    }
    int lg[300006],f[300006][26],a[300006];
    int s[300006];
    int sum[300006];
    int n,m;
    int check(int x,int y){
        if(y<x) return 1<<30;
        int hh=lg[y-x+1];
        int maxn=max(f[x][hh],f[y-(1<<hh)+1][hh]);
        return maxn;
    }
    int main()
    {
        //freopen("hh.out","w",stdout);
        n=rd();
        lg[0]=-1;
        sum[1]=0;
        for(int i=1;i<=n;i++){
            s[i]=rd();
            a[i]=rd();
            f[i][0]=a[i];
            lg[i]=lg[i>>1]+1;
        }
        for(int j=1;j<=25;j++) for(int i=1;i+(1<<j-1)<=n;i++) f[i][j]=max(f[i][j-1],f[i+(1<<j-1)][j-1]);
        m=rd();
        for(int i=1;i<=m;i++){
            int x=rd(),y=rd();
            //cout<<i<<" "; 
            if(y<=x){//后面的年份小,明显不符合 
                printf("false
    ");
                continue;
            }
            int h1=lower_bound(s+1,s+n+1,x)-s;
            int h2=lower_bound(s+1,s+n+1,y)-s;
            if(s[h1]!=x&&s[h2]!=y){//两个年份都没有 
                printf("maybe
    ");
                continue;
            }
            if((s[h2]!=y&&s[h1]==x&&(check(h1+1,h2-1)<a[h1]||h1+1==h2))){
                /*
                前面的有但是后面的没有,必定不为true 
                这时需要判断中间值是否严格小于前端点
                是的话为maybe
                否则为false 
                还要特判h1和h2是否相邻 
                (下标一定要注意) 
                */ 
                printf("maybe
    ");
                continue;
            }
            if((s[h1]!=x&&s[h2]==y&&(check(h1,h2-1)<a[h2]||h1==h2))){
                /*
                后面的有前面的没有,
                判断中间值是否严格小于后端点 
                特判两个点是否为同一个下标 
                */ 
                printf("maybe
    ");
                continue;
            }
            if(s[h1]==x&&s[h2]==y){//前后点都有 
                //cout<<h1<<" "<<h2;
                if(h1+1==h2&&a[h2]<=a[h1]){//如果相邻就特判 
                    if(h2-h1==y-x){//没有空缺 
                        printf("true
    ");
                        continue;
                    }
                    if(h2-h1!=y-x){//有空缺 
                        printf("maybe
    ");
                        continue;
                    }
                }
                if(check(h1+1,h2-1)<a[h1]&&check(h1+1,h2-1)<a[h2]&&a[h2]<=a[h1]){//满足中间值小于后端点,后端点小于等于前端点 
                    if(y-x>h2-h1){//没有空缺 
                        printf("maybe
    ");
                        continue;
                    }
                    if(y-x==h2-h1){//有空缺 
                        printf("true
    ");
                        continue;
                    }
                }
            }
            printf("false
    ");//在其他的判玩后剩下的一定都是false 
        }
        return 0;
    }
    蒟蒻总是更懂你✿✿ヽ(°▽°)ノ✿
  • 相关阅读:
    Redis "MISCONF Redis is configured to save RDB snapshots, but is currently not able to persist on disk"问题的解决
    素描
    python 标准库
    Python内置函数filter, map, reduce
    Python的lambda表达式
    python中super关键字的用法
    python一个注意的地方
    python中self,cls
    python中的实例方法、静态方法、类方法、类变量和实例变量
    python模块及包的导入
  • 原文地址:https://www.cnblogs.com/WWHHTT/p/9676517.html
Copyright © 2020-2023  润新知