Mayor's posters--贴海报

题目

Bytetown城市要进行市长竞选,所有的选民可以畅所欲言地对竞选市长的候选人发表言论。为了统一管理,城市委员会为选民准备了一个张贴海报的electoral墙。 
张贴规则如下: 
electoral墙是一个长度为N个单位的长方形,每个单位记为一个格子; 
所有张贴的海报的高度必须与electoral墙的高度一致的; 
每张海报以“A B”表示,即从第A个格子到第B个格子张贴海报; 
后贴的海报可以覆盖前面已贴的海报或部分海报。 
现在请你判断,张贴完所有海报后,在electoral墙上还可以看见多少张海报。 
输入输出格式 
输入格式: 
第一行: N M 分别表示electoral墙的长度和海报个数 
接下来M行:AiAi BiBi表示每张海报张贴的位置 
输出格式: 
输出贴完所有海报后,在electoral墙上还可以看见的海报数。 
输入输出样例 
输入样例#1: 
100 5 
1 4 
2 6 
8 10 
3 4 
7 10 
输出样例#1: 
4


分析

1、为每个poster编号1,2,3...,利用数组记录poster的起始和终止位置,如果出现相同位置,编号大的覆盖编号小的:

第一个海报[1, 4],第一格和第四格标记为1:

1  1      

 

第二个海报[2, 6],第二格和第六格标记为2:

12 1 2    

 

第三个海报[8, 10],第八格和第十格标记为3:

12 1 2 3 3

 

第四个海报[3, 4],第三格和第四格标记为4(第四格的1<4,被覆盖):

1244 2 3 3

 

第五个海报[7, 10],第七格和第十格标记为5(第十格的3<5,被覆盖):

1244 253 5

2、用最大堆判断poster是否能被看见

一开始最大堆maxHeap为空,可以看见的poster数量 res = 0;

第一个格子为1,编号为1 的poster可以在第一格被看见,1加入最大堆maxHeap,此时maxheap = [1],res = 1;

第二个格子为2,maxheap 最大值为1,说明编号为2 的poster不会被之前的poster覆盖住(编号为2的poster比编号1的poster后贴,在1的上面),可以在第二格被看见,2加入最大堆maxHeap,此时maxheap = [2,1] ,res = 2(编号1、2两张poster都可以看见);

第三个格子为4,maxheap 最大值为2,说明编号为24的poster不会被之前的poster覆盖住可以在第三格被看见,4加入最大堆maxHeap,此时maxheap = [4,2,1] ,res = 3(编号1、2、4三张poster都可以看见);

第四个格子为4,maxheap中存在4,ok,这张海报在这一格就结束了,后面没有这张海报了,4从maxHeap中移除,此时maxheap = [2,1] ,res = 3(编号1、2、4三张poster都可以看见);

第五个格子为0,跳过;

第六个格子为2,maxheap中存在2,ok,编号2的海报在这一格就结束了,后面没有这张海报了,2从maxHeap中移除,此时maxheap = [1] ,res = 3(编号1、2、4三张poster都可以看见);

第七个格子为5,maxheap 最大值为1,5加入最大堆maxHeap,此时maxheap = [5,1] ,res = 4(编号1、2、4、5三张poster都可以看见);

第八个格子为3,maxheap 最大值为5,说明编号为3的poster被编号5的poster覆盖了,看不见,此时maxheap = [5,1] ,res = 4(编号1、2、4、5四张poster都可以看见);

第九个格子为0,跳过;

第十个格子为5,maxheap中存在5,ok,编号5的海报在这一格就结束了,后面没有这张海报了,5从maxHeap中移除,此时maxheap = [1] ,res = 4(编号1、2、4、5四张poster都可以看见);

结束了~结果res=4

 

优化

上面代码的空间复杂度还是比较大,为N(墙的长度,样例中为100,就是步骤1存poster始终位置的数组啦),可以进行进一步优化为 <=2*M

样例所有需要的格子编号为:

1  2  3  4  6  8  10,对应为:

1  2  3  4  5  6  7.

代码如下:

import java.util.Arrays;
import java.util.Comparator;
import java.util.PriorityQueue;
import java.util.Scanner;
import java.util.TreeMap;
public class Main {
	public static void main(String args[]){
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		int m = sc.nextInt();
		
		//步骤一:构建对应map, key:区间的起/终点,value:poster编号
		TreeMap<Integer, Integer> map = new TreeMap<>();
		for(int i=1;i<=m;i++){
			map.put(sc.nextInt(), i);
			map.put(sc.nextInt(), i);
		}
        //优化:对应后的新arr
		int [] arr = new int[map.size()];
		int index = 0;
		for(int item:map.keySet()){
			arr[index++] = map.get(item);
		}

		//最大堆
		PriorityQueue<Integer> maxHeap = new PriorityQueue<>(m*2,new Comparator<Integer>() {
			public int compare(Integer i1,Integer i2){
				return i2-i1;
			}
		});
		//步骤2:维护最大堆
		int res = 0;
		for(int i=0;i<arr.length;i++){

			if(maxHeap.peek()==null||maxHeap.peek()<arr[i]){
				maxHeap.offer(arr[i]);
				res++;
			}
			else{
				if(maxHeap.contains(arr[i]))
					maxHeap.remove(arr[i]);
			}
		}
		System.out.println(res);	
	}
}

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值