1067: [SCOI2007]降雨量

1067: [SCOI2007]降雨量

Time Limit: 1 Sec   Memory Limit: 162 MB
Submit: 2729   Solved: 704
[ Submit][ Status][ Discuss]

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


将年份离散化存到线段树里,然后就是傻逼题啦!
傻逼题?!!!
这题得注意一些特判(苟蒻RT了。。。)
比如说要查询的年份全部大于或者小与值域呀,记住一定不能在查询线段树的时候查空点!!!
一般ql > qr就可能出事情。。。。。
总之尽力避免,加上特判!!!!

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<stack>
#include<cmath>
using namespace std;

const int maxn = 2e5 + 10;

int num[maxn],rain[maxn],n,m,i,j,to[maxn];
int c[4*maxn],ql,qr;

stack <int> s;

void b_t(int o,int l,int r)
{
	if (l == r)
	{
		c[o] = rain[l];
		return;
	}
	
	int mid = (l + r) >> 1;
	b_t(2*o,l,mid); b_t(2*o+1,mid+1,r);
	c[o] = max(c[2*o],c[2*o+1]);
}

int Q(int o,int l,int r)
{
	if (ql <= l && r <= qr) return c[o];
	
	int ret = 0;
	int mid = (l + r) >> 1;
	if (ql <= mid) ret = max(ret,Q(2*o,l,mid));
	if (qr > mid) ret = max(ret,Q(2*o+1,mid+1,r));
	return ret;
}

int query(int x,int y)
{
	ql = x,qr = y;
	return Q(1,1,n);
}

void P1(bool f)
{
	if (f) printf("true\n");
	else printf("false\n");
}

void P2(bool f)
{
	if (f) printf("maybe\n");
	else printf("false\n");
}

int main()
{
	#ifdef YZY
		freopen("yzy.txt","r",stdin);
	#endif
	
	cin >> n;
	for (i = 1; i <= n; i++) scanf("%d%d",&num[i],&rain[i]);
	n++; num[n] = 2E9; rain[n] = 2E9;
	for (i = 1; i <= n; i++)
	{
		if (s.empty())
		{
			s.push(i);
			continue;
		}
		if (num[i] - num[s.top()] > 1)
		{
			int end = s.top();
			while (!s.empty())
			{
				to[s.top()] = end;
				s.pop();
			}
		}
		s.push(i);
	}
	if (!s.empty())
	{
		int end = s.top();
		while (!s.empty())
		{
			to[s.top()] = end;
			s.pop();
		}
	}
	b_t(1,1,n);
	
	cin >> m;
	while (m--)
	{
		int L,R;
		bool flag = 1,t = 0;
		scanf("%d%d",&L,&R);
		if (R <= num[1])
		{
			P2(1);
			continue;
		}
		if (L >= num[n-1])
		{
			P2(1);
			continue;
		}
		if (L == R)
		{
			printf("true\n");
			continue;
		}
		if (L > R)
		{
			printf("false\n");
			continue;
		}
		int a = lower_bound(num + 1,num + n + 1,L) - num;
		int b = lower_bound(num + 1,num + n + 1,R) - num;
		if (num[a] > L || num[b] > R || to[a] < b) flag = 0;
		if (flag)
		{
			if (rain[a] >= rain[b] && query(a+1,b-1) < rain[b]) t = 1;
			P1(t);
		}
		else
		{
			t = 1;
			if (num[a] == L && num[b] == R) 
			  if (rain[a] < rain[b]) t = 0;
			int Left = 2E9;
			if (num[a] == L) Left = rain[a],++a;
			int Right = 2E9;
			if (num[b] == R) Right = rain[b];
			--b;
			int Max = query(a,b);
			if (Max >= Left || Max >= Right) t = 0;
			P2(t);
		}
	}
	return 0;
}


你可能感兴趣的:(1067: [SCOI2007]降雨量)