题目描述
我们常常会说这样的话:“ 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^91≤n≤50000,1≤m≤10000,−109≤yi≤109,1≤ri≤109
这是一段扯淡,不想看的直接往下翻
这是Lv神考试的T2,考场上只知道写一个St表,但是数据范围看错了,下标直接用了年份,里面的判断也写得狗屁不通,然后被卡爆了。
靠后本着一定要学会的精神开始调,看了个超短的题解,学会了怎么用lower_bound,然后瞎搞一波就能过,然后就开开心心的写了一发
……
然后就成功的WA了三个点,RE了七个点,调了一下午也没调出来(一起的学弟昨天就切了)
厚着脸皮去问了他们,被告知了一个一样的方法,然后心态就很爆炸
可能是他们的思想太过高深,我太菜了,见着自己的新思路重写了一个
下了数据后跑了发对拍,发现错的乱七八糟的
然后用了二十分钟重构了代码,对着数据和标程拍了一会儿
过了五个点,还是最大的数据,心想应该是小数据hack了
时间已经过了一个下午,去食堂随便吃了顿饭(还和大佬打了快乐篮球)
回来继续调,加了一个判断条件,六十分,然后找了F姓dalao帮忙,
大佬一口咬定是我写的太丑了(我也是这么想的QAQ)
然后dalao在期间郑重向我表明我的某行代码不是错的,
经过了半个小时的懵逼,我们把刚才说的那行代码改了,然后就A了,后来才知道是出现了重复状态
dalao已经在豆腐上撞死了,我发现自己被安排的明明白白的。
下面是正经的题解
#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; }