1、吞吞大作战
2、混乱的键盘
题目描述:
吞吞大作战是球球大作战的x.0版本,此时球球不能通过击败其他球球壮大自己,而是获得得分,每一个球球都有一个能量值a_i,能量大的球球i可以击败能量小的球球,当一个球球被击败后,击败者可以获得b_i得分,但是为了和谐,每个球球最多只能击败m个其他球球,然后就会强制进入结算环节。数据保证不会有两个球球具有相同的能量值。
请问每个球球最终最多得分多少。
输入描述:
输入第一行包含两个正整数n和m,表示球球的数量,和每个球求最多击败其他球球的数量。
(1<=n, m<=1e5
)
输入第二行包含n个非负整数,表示每个球球的能量值,每个数都不大于100000。
输入第三行包含n个正整数,表示每个球球被击败后对手获得的得分,每个整数都不大于100000。
输出描述:
输出包含n个整数,表示每个球球最终最多获得的分数。
样例输入:
5 3
1 3 5 2 4
1 2 3 4 5
样例输出:
0 5 11 1 7
分析:
借助优先队列【堆排序】
1、利用二维数组去记录球球的能量以及被击败后的得分值 ball[n][2]
,并按照球球的能量值排序
2、因为要于输入的顺序一一对应,那么可以通过一个map来记录 key来存放球球的能量值,value来存放出现的下标值
3、定义ans数组 存放结果 ans[map.get(ball[0][0])]=0
; 下标通过map获取,获取map中的哪个Value,通过ball[i][0]
作为key来获取
4、优先队列控制队列中仅有m个数字【pq.size<=m
】,而当pq.size>m
时,需要将最小的元素弹出
public class Main{
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt(); //球的个数
int m = sc.nextInt();//可以击败球的个数
int[][] ball = new int[n][2];
HashMap<Integer,Integer> map = new HashMap<>();
sc.nextLine();
String s = sc.nextLine();
String[] s1 = s.split(" ");
for(int i=0;i<n;i++){
ball[i][0] = Integer.parseInt(s1[i]);
map.put(ball[i][0],i);
}
s=sc.nextLine();
String[] s2 = s.split(" ");
for(int i=0;i<n;i++){
ball[i][1] = Integer.parseInt(s2[i]);
}
Arrays.sort(ball, new Comparator<int[]>() {
@Override
public int compare(int[] o1, int[] o2) {
return o1[0]-o2[0];
}
});
PriorityQueue<Integer> pq = new PriorityQueue<>(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o1-o2;
}
});
long[] ans = new long[n];
ans[map.get(ball[0][0])]=0;
pq.add(ball[0][1]);
int sum =ball[0][1];
for(int i=1;i<n;i++){
if(pq.size()>m){
long x = pq.peek();
sum = sum- pq.poll();
}
ans[map.get(ball[i][0])] = sum;
sum = sum+ball[i][1];
pq.add(ball[i][1]);
}
for(long x:ans){
System.out.print(x+" ");
}
}
}
题目描述:
小可每天都要将很多的文件输入到电脑里面取 ,由于键盘的长期使用,导致键盘出现了一些bug,如果连续敲击某个键k次后,再次敲击该键位的话,却不会有任何的输入,这个bug可以通过两种方式解决,一种是在这个时候敲击另外一个键位,或者是再敲击k次这个键位,从而使得这个bug被修复。
现在小可又收到了一份文件,文件里面有着一堆这样的连续的需要被键入的文字,但是由于小可使用的键盘是特制的字符集巨大的键盘,所以她不能使用删除键来进行操作,所以小可想知道,如果她需要输入接下来的这个文件,那么她需要以怎样的方式来敲击键盘?但如果你把小可需要输出的字符堆在她面前,过于冗长了,因此小可只想知道对于每个键,小可需要敲击多少次?
输入描述:
输入数据共n+1行
第一行输入2个整数n,k,表示文件的连续段数目和产生bug的临界值
接下来行,每行2个正整数a_i, b_i, 表示a_i这个字符将会紧接着输入b_i 次
对于所有的数据 1<=n, k<=10^5, a_i<=10^9, b_i<=10^9
输出描述:
输出共m+1行(m为字符的种类数)
第一行,输出一个整数m,表示小可需要敲击的键位数。
接下来m行,每行两个正整数 c_i , d_i 表示 c_i 这个字符键被敲击了 d_i 次。
注意此处需要按照 c_i 大小从小往大的顺序输出。
样例输入:
6 4
1 3
1 3
2 1
1 9
2 2
2 10
样例输出:
2
1 27
2 21
分析:
1、在从键盘获取数据的时候,就进行了预处理,将连续字符一样的,连续敲击数直接相加即可
由测试用例可得:
1 6
2 1
1 9
2 12
2、在预处理之后,定义一个map,key:键盘字符 value:敲击次数。根据设置的产生bug的临界值去计算需要敲击的键盘次数【而map直接会将key相同的结果相加到一起】
由测试用例可得:
1 27
2 21
3、输出map.size(); 遍历map集合输出即可? 因为一直觉得HashMap会按照key值大小进行自动排序
但是 HashMap的底层是哈希表,输入的值(3,2,1)经过哈希函数的映射刚好以(1,2,3)的顺序保存,当数据插入过多会发生哈希冲突,这个时候由于是使用链地址法来处理哈希冲突,所以输出的值将不是有序的。
因此需要继续处理 将map中的数据转到list中进行排序,再进行输出。
public class Main{
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String s = sc.nextLine();
int n = Integer.parseInt(s.split(" ")[0]); //连续段落数
int k = Integer.parseInt(s.split(" ")[1]); //产生bug的临界值
List<List<Long>> charTimes = new ArrayList<>();
for(int i=0;i<n;i++){
s = sc.nextLine();
long a = Integer.parseInt(s.split(" ")[0]);
long b = Integer.parseInt(s.split(" ")[1]);
if(charTimes.size()==0){
List<Long> charTime = new ArrayList<>();
charTime.add(a);
charTime.add(b);
charTimes.add(charTime);
}else{
if(charTimes.get(charTimes.size()-1).get(0)==a){
charTimes.get(charTimes.size()-1).set(1,charTimes.get(charTimes.size()-1).get(1)+b);
}
else{
List<Long> charTime = new ArrayList<>();
charTime.add(a);
charTime.add(b);
charTimes.add(charTime);
}
}
}
Map<Long,Long> nums = new HashMap<>();
for(int i=0;i<charTimes.size();i++){
long a = charTimes.get(i).get(0);
long b = charTimes.get(i).get(1);
long times = b/k;
if(b%k==0) times--;
nums.put(a,nums.getOrDefault(a,0L)+times*k+b);
}
List<List<Long>> ans = new ArrayList<>();
for(long num: nums.keySet()){
List<Long> temp = new ArrayList<>();
System.out.println(num+" "+nums.get(num));
temp.add(num);
temp.add(nums.get(num));
ans.add(temp);
}
Collections.sort(ans, new Comparator<List<Long>>() {
@Override
public int compare(List<Long> o1, List<Long> o2) {
return (int) (o1.get(0)-o2.get(0));
}
});
System.out.println(ans.size());
for(int i=0;i< ans.size();i++){
System.out.println(ans.get(i).get(0)+" "+ans.get(i).get(1));
}
}
}