【Luogu P2471】[SCOI2007]降雨量

Luogu P2471
啊啊啊啊这真是一道史上最毒瘤的题目!!!!!
题意就是给出n个年份的降雨量
询问:“自从\(y\)年以来\(x\)年的降雨量最大”的正确性。
显然有多种情况需要考虑,那么就需要通过分类讨论理清程序的逻辑了。
对于“自从\(y\)年以来\(x\)年的降雨量最大”这样一句话,可以转化成如下条件:
\(rain[x]<=rain[y]且\forall a \in [y+1,x-1]有rain[a]<rain[x]\)

经过这样的转化,我们就可以对各种情况进行分类讨论了。
定义:\(query(x,y)\)等于\(rain[x...y]\)的最大值

\[ ①rain[y]未知,rain[x]已知的情况:若此时query(y+1,x-1)>=rain[x]则导出false,反之则导出maybe\\ ②rain[x]未知,rain[y]已知:若此时query(y+1,x-1)>=rain[y]则导出false,反之则导出maybe\\ ③rain[x]、rain[y]均未知:则导出maybe\\ ④两者皆已知:rain[x]>rain[y]导出false;query(y+1,x-1)>=rain[x]导出false\\ 若以上两个条件均不符合,则不可能再导出false\\ 此时再判断:若\exists a \in [y+1,x-1] 有rain[a]未知,则导出maybe\\ 以上所有情况皆不符合则导出true \]

那么剩下的事情就是把这个东西写成代码了。
Query函数可以用线段树或者st表实现。
如果使用线段树,请记住开4倍空间。
否则将像我一样疯狂WA50。(血的教训)

#include<cstdio>
#include<algorithm>
#define lson root<<1
#define rson root<<1|1
#define mid ((l+r)>>1)
using namespace std;
int tree[4*50005],rain[50005],year[50005],n,m,x,y;
void push_up(int root)
{
	tree[root]=max(tree[lson],tree[rson]);
}
void build(int root,int l,int r)
{
	if (l==r)
	{
		tree[root]=rain[l];
		return ;
	}
	build(lson,l,mid);
	build(rson,mid+1,r);
	push_up(root);
}
int query_max(int root,int l,int r,int al,int ar)
{
	if (al<=l&&r<=ar) return tree[root];
	if (l>ar||al>r) return 0;
	int ret=0;
	ret=max(ret,query_max(lson,l,mid,al,ar));
	ret=max(ret,query_max(rson,mid+1,r,al,ar));
	return ret;
}
int main()
{
	scanf("%d",&n);
	for (int i=1;i<=n;i++) scanf("%d%d",&year[i],&rain[i]);
	build(1,1,n);
	scanf("%d",&m);
	for (int i=1;i<=m;i++)
	{
		scanf("%d%d",&y,&x);
		if (x<=y) 
		{
			printf("false\n");
			continue;
		}
		int locx=lower_bound(year+1,year+n+1,x)-year;
		int locy=lower_bound(year+1,year+n+1,y)-year;
		if (x==y+1)//其实不需要特判,只要在query函数中加一个判断,如果区间不合法则返回0即可。
		{
			if (year[locx]!=x) printf("maybe\n");
			else if (year[locy]!=y) printf("maybe\n");
			else if (rain[locx]<=rain[locy]) printf("true\n");
			else printf("false\n");
			continue;
		} 
		else
		{
			int lx=year[locx],ly=year[locy];
			if (lx==x&&ly!=y)
			{
				if (query_max(1,1,n,locy,locx-1)>=rain[locx]) printf("false\n");
				else printf("maybe\n");
			}
			if (lx!=x&&ly==y)
			{
				if (query_max(1,1,n,locy+1,locx-1)>=rain[locy]) printf("false\n");
				else printf("maybe\n");	
			}
			if (lx!=x&&ly!=y) printf("maybe\n");
			if (lx==x&&ly==y)
			{
				if (rain[locx]<=rain[locy])
				{
					if (query_max(1,1,n,locy+1,locx-1)<rain[locx])
					{
						if (locx-locy==x-y) printf("true\n");
						else printf("maybe\n");
					}
					else printf("false\n");
				}
				else printf("false\n");
			}
		}
	}
	return 0;
}
posted @ 2019-11-27 14:55  Nanjo  阅读(128)  评论(0编辑  收藏  举报