zoukankan      html  css  js  c++  java
  • 【bzoj1067】[SCOI2007]降雨量 倍增RMQ

    题目描述

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

    输入

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

    输出

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

    样例输入

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

    样例输出

    false
    true
    false
    maybe
    false


    题解

    倍增RMQ

    分类讨论:

    1. 如果 $l$ 和 $r$ 都未知:显然答案为maybe。
    2. 如果 $l$ 未知而 $r$ 已知:如果 $[l+1,r-1]$ 中有大于等于 $r$ 的则答案为false;否则为maybe。
    3. 如果 $l$ 已知而 $r$ 未知:如果 $[l+1,r-1]$ 中有大于等于 $l$ 的则答案为false;否则为maybe。
    4. 如果 $l$ 和 $r$ 都已知:如果 $r$ 比 $l$ 大,或者 $[l+1,r-1]$ 中有大于等于 $r$ 的则答案为false;否则如果 $[l+1,r-1]$ 均给出则答案为true;否则为maybe。

    具体使用二分查找寻找到在给出序列中的位置以及判断是否均给出,使用倍增RMQ求区间最大值。

    时间复杂度 $O(nlog n)$ 。

    #include <cstdio>
    #include <algorithm>
    #define N 50010
    using namespace std;
    int n , a[N] , v[N] , mx[N][17] , log[N];
    inline int is_full(int l , int r)
    {
    	int x = lower_bound(a + 1 , a + n + 1 , l) - a , y = upper_bound(a + 1 , a + n + 1 , r) - a - 1;
    	return r - l == y - x;
    }
    inline int query(int l , int r)
    {
    	int x = lower_bound(a + 1 , a + n + 1 , l) - a , y = upper_bound(a + 1 , a + n + 1 , r) - a - 1 , k;
    	if(x > y) return 0;
    	k = log[y - x + 1];
    	return max(mx[x][k] , mx[y - (1 << k) + 1][k]);
    }
    int main()
    {
    	int m , i , j , l , r , tl , tr , tm;
    	scanf("%d" , &n);
    	for(i = 1 ; i <= n ; i ++ ) scanf("%d%d" , &a[i] , &v[i]) , mx[i][0] = v[i];
    	for(i = 2 ; i <= n ; i ++ ) log[i] = log[i >> 1] + 1;
    	for(i = 1 ; i <= log[n] ; i ++ )
    		for(j = 1 ; j <= n - (1 << i) + 1 ; j ++ )
    			mx[j][i] = max(mx[j][i - 1] , mx[j + (1 << (i - 1))][i - 1]);
    	scanf("%d" , &m);
    	while(m -- )
    	{
    		scanf("%d%d" , &l , &r);
    		tl = query(l , l) , tr = query(r , r);
    		tm = query(l + 1 , r - 1);
    		if(!tl && !tr) puts("maybe");
    		else if(!tl)
    		{
    			if(tm >= tr) puts("false");
    			else puts("maybe");
    		}
    		else if(!tr)
    		{
    			if(tm >= tl) puts("false");
    			else puts("maybe");
    		}
    		else
    		{
    			if(tl < tr || tm >= tr) puts("false");
    			else if(is_full(l + 1 , r - 1)) puts("true");
    			else puts("maybe");
    		}
    	}
    	return 0;
    }
    

     

  • 相关阅读:
    matplotlib学习之(四)设置线条颜色、形状
    Python 安装matplotlib,six,dateutil,pyparsing 完整过程
    Python中的Numpy、SciPy、MatPlotLib安装与配置
    pip --upgrade批量更新过期的python库
    Python模块常用的几种安装方式
    python文件目录操作
    Python调用(运行)外部程序
    使用CreateProcess函数运行其他程序
    Python中四种运行其他程序的方式
    Python对Excel操作详解
  • 原文地址:https://www.cnblogs.com/GXZlegend/p/8507456.html
Copyright © 2011-2022 走看看