[BZOJ1067/Luogu2471][SCOI2007]降雨量

题目链接:

BZOJ1067

Luogu2471

来了来了,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\)种情况?

posted @ 2018-12-20 19:16  LanrTabe  阅读(136)  评论(0编辑  收藏  举报