• 加农炮 51Nod


    一个长度为M的正整数数组A,表示从左向右的地形高度。测试一种加农炮,炮弹平行于地面从左向右飞行,高
    度为H,如果某处地形的高度大于等于炮弹飞行的高度H(Ai >= H),炮弹会被挡住并落在i - 1处,则Ai−1 + 1。
    如果H <= A0,则这个炮弹无效,如果H > 所有的Ai,这个炮弹也无效。现在给定N个整数的数组B代表炮弹高
    度,计算出最后地形的样子。例如:地形高度A = {1, 2, 0, 4, 3, 2, 1, 5, 7}, 
    炮弹高度B = {2, 8, 0, 7, 6, 5, 3, 4, 5, 6, 5},最终得到的地形高度为:{2, 2, 2, 4, 3, 3, 5, 6, 7}。 

    Input:

    第1行:2个数M, N中间用空格分隔,分别为数组A和B的长度(1 <= m, n <= 50000)
    第2至M + 1行:每行1个数,表示对应的地形高度(0 <= Ai <= 1000000)。
    第M + 2至N + M + 1行,每行1个数,表示炮弹的高度(0 <= Bi <= 1000000)。

    Output:

    输出共M行,每行一个数,对应最终的地形高度。

    Sample Input:

    9 11
    1
    2
    0
    4
    3
    2
    1
    5
    7
    2
    8
    0
    7
    6
    5
    3
    4
    5
    6
    5

    Sample Output:

    2
    2
    2
    4
    3
    3
    5
    6
    7

    思路:

    这个题数据给的不严,暴力有很多种方法可以跑过去,不过还是推荐线段树。

    没啥坑点,就是注意点更新。

    因为找到的点往往是第一个>=炮弹的点而要更新的是前一个点。不能直接通过下标减一来更新。

    因为会有几种特殊情况:


    如图中的【4,4】点和【2,2】点还有【6,6】点和【5,5】 点,后一个点无法通过下标减一来找到前一个点。

    所以推荐用数组记录下每个叶子对应的下标。

    代码:

    #include<stdio.h>
    #include<iostream>
    #include<queue>
    #include<cstring>
    #include<cmath>
    
    using namespace std;
    
    int board[50005][2];//存地形高度和对应的在map里的下标 
    
    int map[700005];
    int m,n;
    
    void Build(int head,int tail,int now)
    {
    	if(head == tail)
    	{
    		map[now] = board[head][0];
    		board[head][1] = now;
    		return ;
    	}
    	int mid = (head+tail)/2;
    	Build(head,mid,now<<1);
    	Build(mid+1,tail,now<<1|1);
    
    	map[now] = max(map[now<<1],map[now<<1|1]);
    }
    
    void p(int now) //用于叶结点更新后更新线段树 
    {
    	if(now == 1)return ;
    	if(now&1)
    	{
    		if(map[now]>map[(now-1)/2])
    		{
    			map[(now-1)/2] = map[now];
    			p((now-1)/2);
    		}
    	}
    	else
    	{
    		if(map[now]>map[now/2])
    		{
    			map[now/2] = map[now];
    			p(now/2);
    		}
    	}
    }
    
    void Updata(int head,int tail,int now,int val)
    {
    	if(head == tail)
    	{
    		if(head == 1)return;
    		board[head-1][0]++;
    		map[board[head-1][1]] = board[head-1][0];
    		p(board[head-1][1]);
    		return ;
    	}
    
    	int mid = (head+tail)/2;
    	if(map[now<<1]>=val)Updata(head,mid,now<<1,val);
    	else Updata(mid+1,tail,now<<1|1,val);
    
    }
    
    
    int main()
    {
    	scanf("%d %d",&m,&n);
    	for(int i=1 ; i<=m ; i++)
    	{
    		scanf("%d",&board[i][0]);
    	}
    
    	Build(1,m,1);
    
    	while(n--)
    	{
    		int mid;
    		scanf("%d",&mid);
    		if(mid>map[1])continue;
    		Updata(1,m,1,mid);
    	}
    	
    	for(int i=1 ; i<m ; i++)printf("%d
    ",board[i][0]);
    	printf("%d",board[m][0]);
    	
    	return 0;
    }


  • 相关阅读:
    Atitit.eclise的ide特性abt 编译
    Atitit python3.0 3.3 3.5 3.6 新特性 Python2.7新特性1Python 3_x 新特性1python3.4新特性1python3.5新特性1值得关注的新特性1Pyth
    Atitit. Atiposter 发帖机 新特性 poster new feature   v7 q39
    Atitit.eclipse 4.3 4.4  4.5 4.6新特性
    atitit.错误:找不到或无法加载主类 的解决 v4 qa15.doc
    Atitit RSA非对称加密原理与解决方案
    Atitti.数字证书体系cer pfx attilax总结
    Atitit ftp原理与解决方案
    Atitit qzone qq空间博客自动点赞与评论工具的设计与实现
    Atitit 软件国际化原理与概论
  • 原文地址:https://www.cnblogs.com/vocaloid01/p/9514291.html
Copyright © 2020-2023  润新知