中兴捧月神算师-算法精英挑战赛-比特派第一场

一、跳高

难度:一颗星
题目描述:

在新的一年,牛牛想跳得更高。牛牛本身可以跳高 h h h米。同时牛牛有 n n n颗跳高弹,使用第 i i i 颗跳高弹可以使牛牛跳高高度增加 a i a_i ai米,且跳高弹的效果是可以叠加的,也就是说如果牛牛使用多颗跳高弹,那么他的跳高高度将会增加这些跳高弹单个效果的和。

每颗跳高弹只能使用一次。

请问牛牛最少需要使用多少个跳高弹,才能让牛牛的高度至少是 u u u米高呢?

数据保证答案存在。

输出描述:
输出一个整数,表示答案。

示例:
输入

3 2 5
1 3 2

输出

1

说明:
只需要使用第2颗跳高弹就可以到达5米。

题解:

import java.util.*;

public class Main {
      public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
          int n = sc.nextInt();
          int[] nums = new int[n];
              int h = sc.nextInt();
        int u = sc.nextInt();
        for (int i = 0; i < n; i++) {
            nums[i] = sc.nextInt();
        }
          
          if(u <= h){
              System.out.println(0);
              return;
          }
        Arrays.sort(nums);
        int count = 0;
        for (int i = n-1; i >= 0; i--) {
            h = h+nums[i];
            count++;
            if (h >= u){
            System.out.println(count);
            return;
            }  
        }
        System.out.println(-1);
    }   
}

二、切绳子

难度:一颗星
题目描述:
牛牛有一条长度为 n n n的绳子。
第一天,绳子的长度为 n n n
第二天,这条绳子会被切成两段长度分别为 ⌊ n 2 ⌋ \left \lfloor \frac{n}{2} \right \rfloor 2n n − ⌊ n 2 ⌋ n-\left \lfloor \frac{n}{2} \right \rfloor n2n
第三天,对于第二天切出来的每段长度大于 1 1 1的绳子,设其长度为 m m m,牛牛又会将其切成
⌊ m 2 ⌋ \left \lfloor \frac{m}{2} \right \rfloor 2m m − ⌊ m 2 ⌋ m-\left \lfloor \frac{m}{2} \right \rfloor m2m
如此反复切下去… …
但是,牛牛知道,终有一天所有的绳子都会被切成长度为{1}1的绳子,到时候他就没有绳子可切了。所有绳子都变成长度为{1}1的绳子是第几天?
注: ⌊ n 2 ⌋ \left \lfloor \frac{n}{2} \right \rfloor 2n表示 n n n除以 2 2 2向下取整

输入描述:
输入包含 T T T组数据,第一行一个整数 T T T
接下来 T T T行每行一个正整数 n n n

输出描述:
输出 T T T行,第 i i i行为第 i i i组数据的答案。

示例:
输入

3
1
2
3

输出

1
2
3

备注:
1 ≤ n ≤ 1 e 18 , 1 ≤ T ≤ 10000 1≤n≤1e18,1≤T≤10000 1n1e18,1T10000

题解:

import java.util.Arrays;
import java.util.Scanner;

public class Main {
public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int T = sc.nextInt();
        long[] nums = new long[T];
        for (int i = 0; i < T; i++) {
            nums[i] = sc.nextLong();
        }

        for (long n : nums) {
            deal(n);
        }
		return;
    }

    public static void deal(long n){
        int i = 1;

        while (n > 1){
            i++;
//             n = (int)Math.max(Math.floor(n/2),n - Math.floor(n/2));
            n = Math.max(n / 2, n - n / 2);
        }
        System.out.println(i);
    }
}

三、做任务

难度:三颗星
题目描述:
假设我们有一些任务列表,任务编号从1开始。不同的任务难度也不一样,分为1-5级。
我们打算把这些任务分配给牛牛,可是牛牛比较懒,每次他接受到一个任务后,他都会从自己的todo list里找到“难度各不相同且编号和最大的五个任务”,然后再一起完成,否则的话,牛牛就把任务放到自己的todo list,什么也不做。
请你根据输入的任务列表的情况,给出牛牛完成任务的情况。
输入描述:
第一行输入一个整数n 表示任务数目。
第二行n个以空格分隔的整数,表示不同的任务难度。
1 ≤ n ≤ 1 0 5 1\leq n \leq 10^{5} 1n105

输出描述:
输出 m a t h i t ( n ) mathit(n) mathit(n)行,表示牛牛每次收到任务后的完成任务情况。如果牛牛什么也没做,就输出-1,否则的话,输出5个整数,分别表示牛牛完成难度为 1 , 2 , 3 , 4 , 5 \text 1,2,3,4,5 1,2,3,4,5的五个任务编号。

示例:
输入

10
1 1 2 2 3 3 4 5 4 5

输出

-1
-1
-1
-1
-1
-1
-1
2 4 6 7 8
-1
1 3 5 9 10

说明:
输出10行,牛牛只有收到第8个和第10个任务的时候,才会完成任务。

题解:

import java.util.*;

public class Main{
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        TreeMap<Integer,Queue<Integer>> map = new TreeMap<>();
        for(int i = 0;i < n;i++){
            int m = sc.nextInt();
            if(!map.containsKey(m)){
                map.put(m, new PriorityQueue<>(Comparator.reverseOrder()));
            }
            map.get(m).add(i+1);
            if(map.size() < 5){
               System.out.println(-1);
            }else{
                Iterator iterator = map.keySet().iterator();
                while(iterator.hasNext()){
                    int key = (int)iterator.next();
                    System.out.print(map.get(key).poll()+" ");
                    if(map.get(key).isEmpty()){
                        iterator.remove();
                     }
                }
                System.out.println();
            }
        }
    }
}

四、换队伍

难度:三颗星
题目描述:

在一个超市里有两个收银台,现在它们面前排了长长的队伍。
第一个收银台前排了 n 1 \mathit n_{1} n1个人,从靠近收银台开始分别编号 1 , 2 , . . . , n 1 1 , 2 , . . . , n 1 \text 1,2,...,n_{1}1,2,...,n 1 1,2,...,n11,2,...,n1
第二个收银台前排了 n 2 \mathit n_{2} n2个人,从靠近收银台开始分别编号 n 1 + 1 , n 1 + 2 , . . . , n 1 + n 2 n_{1}+1,n_{1}+2,...,n_{1}+n_{2} n1+1,n1+2,...,n1+n2

可是总有一些人觉的自己的队伍排的太慢了,会从自己的队伍里离开,然后排在另一个队伍的最后。
那当所有的人都换完队伍后,这两个队伍的编号最后是什么样的呢?

输入描述:
第一行三个以空格分隔的整数 n 1 , n 2 , q \mathit n_{1},n_{2},q n1,n2,q
第二行\mathit qq个以空格分隔的整数,表示离开队伍的编号。
1 ≤ n 1 , n 2 , q ≤ 1 0 5 1\leq n_{1},n_{2},q \leq 10^{5} 1n1,n2,q105
保证离开队伍的人员编号在 [ 1 , n 1 + n 2 ] \text [1,n1+n2] [1,n1+n2]范围内。

输出描述:
共两行整数,分别描述两个队伍的样子,按照离收银台近的位置开始依次给出人员的编号(以空格分隔)。
保证最后两个队伍均至少有一个人。

示例:
输入

3 3 3
2 3 4

输出

1 4
5 6 2 3

说明:

初始时两个队伍的样子为:

1 2 3
4 5 6

当编号为2的人换队伍后,两个队伍的样子为:

1 3
4 5 6 2

接下来当编号为3的人换队伍后,两个队伍的样子为:

1
4 5 6 2 3

接下来当编号为4的人换队伍后,两个队伍的样子为:

1 4
5 6 2 3

题解:

import java.util.*;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
 
public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n1 = sc.nextInt();
        int n2 = sc.nextInt();
        int q = sc.nextInt();
        LinkedList<Integer> q1 = new LinkedList<>();
        HashSet<Integer> set1 = new HashSet<>();
        LinkedList<Integer> q2 = new LinkedList<>();
        HashSet<Integer> set2 = new HashSet<>();
        //给每个队伍分配序号
        for(int i = 0; i < n1 + n2;i++){
            if(i < n1){
                q1.add(i+1);
                set1.add(i+1);
            }else{
                q2.add(i+1);
                set2.add(i+1);
            }
        }
        //换队伍
        for(int i = 0;i < q;i++){
            int num = sc.nextInt();
            //判断是否在队伍中
            if(set1.contains(num)){
                //在队伍1中,移除,排到队伍2后面
                set1.remove(num);
                set2.add(num);
                q2.addLast(num);
            }else{
                set2.remove(num);
                set1.add(num);
                q1.addLast(num);
            }
        }
        //重组
        LinkedList<Integer> res1 = new LinkedList<>();
        while (q1.size() > 0 && set1.size() > 0){
            Integer num = q1.removeLast();
            if (set1.contains(num)){
                res1.addFirst(num);
                set1.remove(num);
            }
        }
         LinkedList<Integer> res2 = new LinkedList<>();
         while (q2.size() > 0 && set2.size() > 0){
            Integer num = q2.removeLast();
            if (set2.contains(num)){
                res2.addFirst(num);
                set2.remove(num);
            }
        }
        //输出
        Iterator<Integer> iterator1 = res1.iterator();
        while (iterator1.hasNext()){
            System.out.print(iterator1.next()+" ");
        }
        System.out.println();
        Iterator<Integer> iterator2 = res2.iterator();
        while (iterator2.hasNext()){
            System.out.print(iterator2.next()+" ");
        }
        System.out.println();
    }
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

柠檬の夏

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值