题目
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:
1 | 2 | 1 | 2 |
第三个海报[8, 10],第八格和第十格标记为3:
1 | 2 | 1 | 2 | 3 | 3 |
第四个海报[3, 4],第三格和第四格标记为4(第四格的1<4,被覆盖):
1 | 2 | 4 | 4 | 2 | 3 | 3 |
第五个海报[7, 10],第七格和第十格标记为5(第十格的3<5,被覆盖):
1 | 2 | 4 | 4 | 2 | 5 | 3 | 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);
}
}