[BZOJ1067/Luogu2471][SCOI2007]降雨量
题目链接:
来了来了,BZOJ著名题目
\(Juruo\)少有的\(1A\)
很明显的一个分类讨论题,分以下\(5\)中情况来讨论。
设\(l,r\)为询问的两个年份,\(Rain_i\)表示\(i\)年的雨量。
-
\(1.\)答案为\(true\)
-
\(Rain_l\sim Rain_r\)已知
-
\(Rain_r<Rain_l\)
-
\(Rain_r>\max\{Rain_{l+1}\sim Rain_{r-1}\}\)
-
-
\(2.\)答案为\(false\)的一种:\(Rain_l,Rain_r\)已知
- \(Rain_r\ge Rain_l\)或\(Rain_r\le\max\{Rain_{l+1}\sim Rain_{r-1}\}\)
-
\(3.\)答案为\(false\)的一种:\(Rain_l\)已知
- \(Rain_l-\max\{Rain_{l+1}\sim Rain_{r-1}\}\le 2\)(没有足够的空隙留给\(Rain_r\))
-
\(4.\)答案为\(false\)的一种:\(Rain_r\)已知
- \(Rain_r\le \max\{Rain_{l+1}\sim Rain_{r-1}\}\)
- \(5.\)其他情况均为\(maybe\)
真简单
关于\(\max\)查询我用的\(ST\)表,好写,常数小。
#include <cstdio>
#include <algorithm>
int n,m;
int Year[50005],Rain[50005];
int Log[50005],f[50005][17];
inline int Max(int l,int r)
{
if(l>r)return -1;
int k=Log[r-l+1];
return std::max(f[l][k],f[r-(1<<k)+1][k]);
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;++i)scanf("%d%d",&Year[i],&Rain[i]);
for(int i=1;i<=n;++i)f[i][0]=Rain[i];
for(int i=2;i<=n;++i)Log[i]=Log[i>>1]+1;//预处理Log
for(int k=1;(1<<k)<=n;++k)
for(int i=1;i+(1<<k)-1<=n;++i)
f[i][k]=std::max(f[i][k-1],f[i+(1<<(k-1))][k-1]);
scanf("%d",&m);
for(int l,r;m--;)
{
scanf("%d%d",&l,&r);
int p1=std::lower_bound(Year+1,Year+n+1,l)-Year;
int p2=std::lower_bound(Year+1,Year+n+1,r)-Year;
if(Year[p1]==l&&Year[p2]==r&&p2-p1==r-l&&Rain[p2]<Rain[p1]&&Rain[p2]>Max(p1+1,p2-1))
puts("true");
else if(Year[p1]==l&&Year[p2]==r&&(Rain[p2]>=Rain[p1]||Rain[p2]<=Max(p1+1,p2-1)))
puts("false");
else if(Year[p1]==l&&Year[p2]!=r&&Rain[p1]-Max(p1+1,p2-1)<2)
puts("false");
else if(Year[p1]!=l&&Year[p2]==r&&Rain[p2]<=Max(p1,p2-1))
puts("false");
else
puts("maybe");
}
return 0;
}
\(Upadte:\)似乎很多人没有考虑第\(3\)种情况?