• 奖品分配-头条2019笔试题


    奖品分配-头条2019笔试题

    有n个人参加编程比赛,比赛结束后每个人都得到一个分数;现在所有人排成一圈(第一个和第n个相邻)领取奖品,要求:

    1、如果某个人的分数比左右的人高,那么奖品数量也要比左右的人多;

    2、每个人至少得到一个奖品;

    问最少应该准备多少个奖品。

    输入格式

    第一行是整数T,表示测试样例个数。

    每个测试样例的第一行是一个整数n,表示参加比赛的人数。

    第二行是n个正整数a[i],表示从第1个人到第n个人的分数。

    输出格式

    对每个测试样例,输出应该准备的最少奖品,每个结果占一行。

    数据范围

    1≤T≤10,
    0<n<(10^5),
    0<a[i]<(10^5)

    输入样例:

    2
    2
    1 2
    4
    1 2 3 3
    

    输出样例:

    3
    8
    

    java 下标排序

    //下标排序
    int[] a = new int[n];
    Integer[] idx = new Integer[n];
    Arrays.sort(idx, (o1, o2)->a[o1]-a[o2]);
    

    奖品分配问题

    方法一、(O(nlog_2^n))

    我们希望当计算第i个小朋友糖果数量时,它左右分数比他低的小朋友糖果数量已经计算出来了,得分相同或大于没有要求。
    因此,我们根据得分排序,得分少的先计算糖果数量。
    如果左右未分配,则分配1
    如果存在分配的,则分配该小朋友左右分配值中最大值+1

    时间复杂度分析,计算次数为:

    [Tnlog_2^n = 10 imes 10^5log_2^{10^5} approx 1.7 imes10^7 ]

    实测java超时, 可能排序常数项较大。

    import java.util.*;
    public class Main{
        public static void main(String[] args){
            Scanner sc = new Scanner(System.in);
            int T = sc.nextInt();
            while(T-- > 0) {
                int n = sc.nextInt();
                int[] a = new int[n];
                
                Integer[] idx = new Integer[n];
                int[] nums = new int[n];
                for(int i=0; i < n; i++) {
                    a[i] = sc.nextInt();
                    idx[i] = i;
                }
                Arrays.sort(idx, (o1, o2)->a[o1]-a[o2]);
                for(int i=0; i < n; i++) {
                    int k = idx[i];
                    int left = (k-1+n)% n, right = (k+1)%n;
                    int maxn = 0;
                    if(a[left] < a[k]) maxn = Math.max(nums[left], maxn);
                    if(a[right] < a[k]) maxn = Math.max(maxn, nums[right]);
                    nums[k] = maxn + 1;
                    //System.out.println("+++"+nums[k]);
                }
                long res = 0L;
                for(int i=0; i < n; i++)
                    res = res + nums[i];
                System.out.println(res);
            }
        }
    }
    

    方法二、记忆化搜索(O(n))

    import java.util.*;
    public class Main {
        static int[] f, a;
        static int n;
        static int dfs(int x) {
            if(f[x] != 0) return f[x];
            if(a[(x+n-1) % n] >= a[x] && a[(x+1) % n] >= a[x] ) 
                return f[x] = 1;
            int v = 0;
            if(a[(x+n-1)% n] < a[x]) 
                v = dfs((x+n-1)% n);
            if(a[(x+1)% n] < a[x]) 
                v = Math.max(v, dfs((x+1)%n));
            return f[x] = v + 1;
        }
        public static void main(String[] args){
            Scanner sc = new Scanner(System.in);
            int T = sc.nextInt();
            while(T-- > 0) {
                n = sc.nextInt();
                a = new int[n];
                f = new int[n];
                for(int i=0; i < n; i++)
                    a[i] = sc.nextInt();
                for(int i=0; i < n; i++)
                    dfs(i);
                long res = 0L;
                for(int i=0; i < n; i++)
                    res = res + f[i];
                System.out.println(res);
            }
        }
    }
    
  • 相关阅读:
    鸡啄米vc++2010系列19(常用控件:静态文本框)
    鸡啄米vc++2010系列18(颜色对话框)
    鸡啄米vc++2010系列17(字体对话框)
    鸡啄米vc++2010系列16(文件对话框)
    鸡啄米vc++2010系列15(消息对话框)
    鸡啄米vc++2010系列14(一般属性页对话框的创建)
    鸡啄米vc++2010系类13(向导对话框的创建)
    鸡啄米vc++2010系列12(属性页对话框)
    鸡啄米vc++2010系列11(非模态对话框的创建)
    鸡啄米vc++2010系列10(模态对话框及其弹出过程)
  • 原文地址:https://www.cnblogs.com/lixyuan/p/12956542.html
Copyright © 2020-2023  润新知