zoukankan      html  css  js  c++  java
  • BZOJ 1067 降雨量(RMQ-ST+有毒的分类讨论)

    1067: [SCOI2007]降雨量

    Time Limit: 1 Sec  Memory Limit: 162 MB
    Submit: 4399  Solved: 1182
    [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

     

     

    题目链接:BZOJ 1067

    这题的分类讨论简直要死,WA很多次才过了,先用RMQ处理出一段区间内的降雨量最大值,然后由于不仔细审题,以为只要y+1~x-1这一段区间内的降雨量严格小于x即可,实际上除了这个条件还需要x的降雨量小于等于y的降雨量:它的含义是X年的降雨量不超过Y年,且对于任意Y<Z<X,Z年的降雨量严格小于X年然后分类讨论区间是否合法,我写的辣鸡代码量比较多,但是感觉比较清楚

    代码:

    #include <stdio.h>
    #include <bits/stdc++.h>
    using namespace std;
    #define INF 0x3f3f3f3f
    #define LC(x) (x<<1)
    #define RC(x) ((x<<1)+1)
    #define MID(x,y) ((x+y)>>1)
    #define CLR(arr,val) memset(arr,val,sizeof(arr))
    #define FAST_IO ios::sync_with_stdio(false);cin.tie(0);
    typedef pair<int, int> pii;
    typedef long long LL;
    const double PI = acos(-1.0);
    const int N = 50010;
    struct info
    {
    	int year;
    	int val;
    };
    info arr[N];
    int maxm[N << 1][20];
    map<int, int>vis;
    
    void RMQ_init(int l, int r)
    {
    	int i, j;
    	for (i = l; i <= r; ++i)
    		maxm[i][0] = arr[i].val;
    	for (j = 1; l + (1 << j) - 1 <= r; ++j)
    		for (i = l; i + (1 << j) - 1 <= r; ++i)
    			maxm[i][j] = max(maxm[i][j - 1], maxm[i + (1 << (j - 1))][j - 1]);
    }
    int ST(int l, int r)
    {
    	int k = log2(r - l + 1);
    	return max(maxm[l][k], maxm[r - (1 << k) + 1][k]);
    }
    int Find(int year, int l, int r)
    {
    	int L = l, R = r, ans = 0;
    	while (L <= R)
    	{
    		int mid = (L + R) >> 1;
    		if (arr[mid].year == year)
    		{
    			ans = mid;
    			break;
    		}
    		else if (arr[mid].year < year)
    			L = mid + 1;
    		else
    			R = mid - 1;
    	}
    	return ans;
    }
    int Find_Lpos(int year, int l, int r)//相当于lower_bound
    {
    	int L = l, R = r, ans = 0;
    	while (L <= R)
    	{
    		int mid = (L + R) >> 1;
    		if (arr[mid].year >= year)
    		{
    			ans = mid;
    			R = mid - 1;
    		}
    		else
    			L = mid + 1;
    	}
    	return ans;
    }
    int Find_Rpos(int year, int l, int r)//相当于upper_bound - 1
    {
    	int L = l, R = r, ans = 0;
    	while (L <= R)
    	{
    		int mid = (L + R) >> 1;
    		if (arr[mid].year <= year)
    		{
    			ans = mid;
    			L = mid + 1;
    		}
    		else
    			R = mid - 1;
    	}
    	return ans;
    }
    int main(void)
    {
    	int n, m, i, x, y;
    	while (~scanf("%d", &n))
    	{
    		vis.clear();
    		for (i = 1; i <= n; ++i)
    		{
    			scanf("%d%d", &arr[i].year, &arr[i].val);
    			vis[arr[i].year] = arr[i].val;
    		}
    		RMQ_init(1, n);
    		scanf("%d", &m);
    		for (i = 0; i < m; ++i)
    		{
    			scanf("%d%d", &y, &x);
    			if (vis[y] && vis[x])
    			{
    				int L = Find(y, 1, n);
    				int R = Find(x, 1, n);
    				if (arr[R].val > arr[L].val) //保证Fx<=Fy
    					puts("false");
    				else if (R - L + 1 == x - y + 1) //中间年份全
    				{
    					if (L + 1 > R - 1) //年份相邻
    						puts("true");
    					else//至少隔了一个单位
    					{
    						int ma = ST(L + 1, R - 1);
    						if (ma < arr[R].val)
    							puts("true");
    						else
    							puts("false");
    					}
    				}
    				else//中间年份残缺
    				{
    					if (L + 1 > R - 1) //输入顺序相邻
    						puts("maybe");
    					else//至少隔了一个输入单位
    					{
    						int ma = ST(L + 1, R - 1);
    						if (ma < arr[R].val)
    							puts("maybe");
    						else
    							puts("false");
    					}
    				}
    			}
    			else if (vis[y] && !vis[x]) //y已知x未知
    			{
    				int L = Find(y, 1, n);
    				int R = Find_Rpos(x, 1, n);
    				if (L == R)
    					puts("maybe");
    				else if (L == R - 1)
    				{
    					if (arr[R].val < arr[L].val)
    						puts("maybe");
    					else
    						puts("false");
    				}
    				else
    				{
    					int ma = ST(L + 1, R);
    					if (ma < arr[L].val)
    						puts("maybe");
    					else
    						puts("false");
    				}
    			}
    			else if (!vis[y] && vis[x]) //y未知x已知
    			{
    				int L = Find_Lpos(y, 1, n);
    				int R = Find(x, 1, n);
    				if (L == R)
    					puts("maybe");
    				else
    				{
    					int ma = ST(L, R - 1);
    					if (ma < arr[R].val)
    						puts("maybe");
    					else
    						puts("false");
    				}
    			}
    			else//均未知,一定是maybe
    				puts("maybe");
    		}
    	}
    	return 0;
    }
  • 相关阅读:
    DDOS攻击与防御
    .NET Core 二维码生成Demo
    腾讯云服务器远程登录卡顿严重导致无法登录解决办法
    signalR【一、官方案例】
    Python题目:生成100个随机不重复的字符串【杭州多测师】【杭州多测师_王sir】
    把字符串当中重复的字符打印出来【杭州多测师】【杭州多测师_王sir】
    PC#1 ping PC#2,请描述PC1和PC2之间的通信过程【杭州多测师】【杭州多测师_王sir】
    逻辑题【杭州多测师】【杭州多测师_王sir】
    编程题:给一个网址获取分配网址的协议,域名,路径,端口,参数1的值,参数2的值,并以字典的形式打印出结果【杭州多测师】【杭州多测师_王sir】
    经典的Python题目之找到a开头的元素、组成新的列表【多测师王sir】【杭州多测师_王sir】
  • 原文地址:https://www.cnblogs.com/Blackops/p/6354251.html
Copyright © 2011-2022 走看看