降雨量(附我的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;
}
蒟蒻总是更懂你✿✿ヽ(°▽°)ノ✿
原文地址:https://www.cnblogs.com/WWHHTT/p/9676517.html