码迷,mamicode.com
首页 > 其他好文 > 详细

【BZOJ 1067】 [SCOI2007]降雨量

时间:2015-02-22 11:05:13      阅读:176      评论:0      收藏:0      [点我收藏+]

标签:bzoj   oi   rmq   map   

1067: [SCOI2007]降雨量

Time Limit: 1 Sec  Memory Limit: 162 MB
Submit: 2211  Solved: 571
[Submit][Status]

Description

我们常常会说这样的话:“X年是自Y年以来降雨量最多的”。它的含义是X年的降雨量不超过Y年,且对于任意Y<Z<X,Z年的降雨量严格小于X年。例如2002,2003,2004和2005年的降雨量分别为4920,5901,2832和3890,则可以说“2005年是自2003年以来最多的”,但不能说“2005年是自2002年以来最多的”由于有些年份的降雨量未知,有的说法是可能正确也可以不正确的。

Input

输入仅一行包含一个正整数n,为已知的数据。以下n行每行两个整数yi和ri,为年份和降雨量,按照年份从小到大排列,即yi<yi+1。下一行包含一个正整数m,为询问的次数。以下m行每行包含两个数Y和X,即询问“X年是自Y年以来降雨量最多的。”这句话是必真、必假还是“有可能”。

Output

对于每一个询问,输出true,false或者maybe。

Sample Input

6
2002 4920
2003 5901
2004 2832
2005 3890
2007 5609
2008 3024
5
2002 2005
2003 2005
2002 2007
2003 2007
2005 2008

Sample Output

false
true
false
maybe
false

HINT

100%的数据满足:1<=n<=50000, 1<=m<=10000, -10^9<=yi<=10^9, 1<=ri<=10^9

Source


RMQ。


维护区间最大值即可。


对于年份,我用map保存,若相邻的年份之间有未知的,把他们缩成一年,于是对于一个区间是否全部已知,用前缀和判断即可。


一些实现上的细节:

1.对于查询,可能会问到未知的年份,需要通过二分查找确定他在map中的对应值


2.若x,y未知,直接特判处理(若x未知,可能是maybe,可能是false!!)


#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#include <map>
#define M 50005
using namespace std;
map<int,int> mp;
int f[M*2][20],r[M*2],now,R[M],y[M],sum[M*2],n,m;
void RMQ()
{
	for (int i=1;i<=now;i++)
		f[i][0]=r[i];
	for (int j=1;(1<<j)<=now;j++)
		for (int i=1;i+(1<<j)-1<=now;i++)
			f[i][j]=max(f[i][j-1],f[i+(1<<(j-1))][j-1]);
}
int Getlog(int x)
{
	if (x==1) return 0;
	int b=1;
	for (int i=0;;i++)
	{
		if (x>b&&x<=b*2) return i;
		b*=2;
	}
}
int Getmax(int l,int r)
{
	if (r<l) return 0;
	int s=Getlog(r-l+1);
	return max(f[l][s],f[r-(1<<s)+1][s]);
}
int Get(int x)
{
	int l=0,r=n,ans=0;
	while (l<=r)
	{
		int m=(l+r)>>1;
		if (y[m]<x) ans=m,l=m+1;
		else r=m-1;
	}
	return mp[y[ans]]+1;
}
int main()
{
        scanf("%d",&n);
	for (int i=1;i<=n;i++)
		scanf("%d%d",&y[i],&R[i]);
	y[0]=-1e9-1;
	mp[y[0]]=0;
	mp[y[1]]=2;
	r[2]=R[1];
	sum[2]=1;
	for (int i=2;i<=n;i++)
	{
		now=mp[y[i-1]]+1;
		if (y[i]>y[i-1]+1) now++;
		mp[y[i]]=now;
		r[now]=R[i];
		sum[now]=1;
	}
	for (int i=1;i<=now;i++)
		sum[i]=sum[i]+sum[i-1];
	RMQ();
	scanf("%d",&m);
	while (m--)
	{
		int x,y;
		scanf("%d%d",&y,&x);
		if (!mp.count(y)) y=Get(y);
		else y=mp[y];
		if (!mp.count(x)) x=Get(x);
		else x=mp[x];
		int k=Getmax(y+1,x-1);
		if (!r[x]) 
		{
			if (!r[y]||!k||r[y]>k) puts("maybe");
			else puts("false");
			continue;
		}
		if (r[x]<=r[y]||!r[y])
		{
			if (k>=r[x]) puts("false");
			else
			{
				if (sum[x]-sum[y-1]==x-y+1) puts("true");
				else puts("maybe");
			}
		}
		else puts("false");
	}
	return 0;
}

技术分享


【BZOJ 1067】 [SCOI2007]降雨量

标签:bzoj   oi   rmq   map   

原文地址:http://blog.csdn.net/regina8023/article/details/43899691

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!