思路
对于一组询问Y和X(也即从Y年到X年),我们来分析什么时候答案为”true“:
1、从Y到X年的降雨量都已知
2、X年的降雨量不超过Y年的降雨量
3、从Y+1到X-1年的降雨量都小于X年的降雨量
只有上述3个条件都满足,答案才为"true”。
接下来考虑什么时候答案为"maybe“:
1-1、Y年和X年的降雨量已知
1-2、X年的降雨量不超过Y年的降雨量
1-3、从Y+1到X-1年中存在至少一年的降雨量未知
1-4、从Y+1到X-1年中已知的降雨量都小于X年的降雨量
2-1、Y年和X年中有且仅有一年的降雨量未知 (Y年未知时需要注意遍历的起点)(在此处 wr 了n次)
2-2、从Y+1到X-1年中已知的降雨量都小于X年的降雨量
3、Y年和X年的降雨量都未知
以上三组条件中只要满足任意一组,答案即为"maybe"。
至于剩下的情况,自然就是"false"了。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long ll;
const int maxn=50010;
int maxsum[maxn][17],yr[maxn],w[maxn]; //yr存放年份 w降水量
void rmq(int n) //预处理
{
for(int i=1;i<=n;i++)
maxsum[i][0]=w[i];
for(int j=1;j<17;j++)
for(int i=1;i<=n;i++)
if(i+(1<<j-1) <= n)
maxsum[i][j]=max(maxsum[i][j-1],maxsum[i+(1<<(j-1))][j-1]);
}
int query(int l,int r)
{
if(l>r)
return -1;
int k=(int)(log(r-l+1.0)/log(2.0));
int ma=max(maxsum[l][k],maxsum[r-(1<<k)+1][k]);
return ma;
}
int main()
{
int n,m;
int x,y;
while(~scanf("%d",&n))
{
memset(w,0,sizeof(w));
for(int i=1;i<=n;i++)
scanf("%d%d",&yr[i],&w[i]);
rmq(n);
int l,r;
scanf("%d",&m);
if(n==0 && m==0)
break;
while(m--) // 查询
{
int k;
scanf("%d%d",&y,&x);
l=lower_bound(yr+1,yr+n+1,y)-yr;
r=lower_bound(yr+1,yr+n+1,x)-yr;
if(yr[l]==y && yr[r]==x && r-l==x-y && w[l]>=w[r]) //y年到x年的降水量都已知(每年都有) y年的降水量不小于x年
{
int h=query(l+1,r-1);
if(h<w[r]) //y+1到x-1年的降水量都小于x年
printf("true\n");
else //不成立则为假
printf("false\n");
}
else if(yr[l]==y && yr[r]==x && w[l]>=w[r] && r-l!=x-y)//y年的降水量不小于x年 y年,x年的降水量已知(x~y至少有一年未知)
{
int h=query(l+1,r-1);
if(h < w[r]) //y+1到x-1年的降水量都小于x年
printf("maybe\n");
else
printf("false\n");
}
else if(yr[l]!=y && yr[r]==x) //y年未知 注意此处需要从y出开始便利
{
int h=query(l,r-1);
if(h < w[r]) //y到x-1年的降水量都小于x年
printf("maybe\n");
else
printf("false\n");
}
else if(yr[l]==y && yr[r]!=x) //x年未知
{
int h=query(l+1,r-1);
if(h < w[l])
printf("maybe\n");
else
printf("false\n");
}
else if(yr[l]!=y && yr[r]!=x) //x,y都未知
printf("maybe\n");
else //其他情况全为假
printf("false\n");
}
printf("\n");
}
return 0;
}
本文参考博客