牛客acm模式——美团2021(第10场)

美团

acm模式的输入输出
美团2021校招笔试-编程题(通用编程试题,第10场)

第一题

在这里插入图片描述
输入描述:

输入第一行仅包含三个正整数n,x,y,分别表示参赛的人数和晋级淘汰人数区间。(1<=n<=50000,1<=x,y<=n)
输入第二行包含n个整数,中间用空格隔开,表示从1号选手到n号选手的成绩。(1<=|a_i|<=1000)

输出描述:

输出仅包含一个整数,如果不存在这样的m,则输出-1,否则输出符合条件的最小的值。

输入
6 2 3
1 2 3 4 5 6
输出
3
let first = readline().split(' ')
let n = parseInt(first[0]), x = parseInt(first[1]), y = parseInt(first[2])
let arrs = readline().split(' ').map(item => parseInt(item))
arrs.sort( (a,b) => {return a - b} )
let l=0, r=n-1
while(l<=r) {
    let mid = l + Math.floor((r-l) / 2)
    let pass = n - mid, fail = mid
    if(pass < x || fail > y){
        r = mid - 1
    } else if(pass > y || fail < x){
        l = mid + 1
    } else {
        r = mid - 1
    }
}
 
let pass = n - l
let fail = l
 
if((pass >= x && pass <= y) && (fail >= x && fail <= y)) {
    print(arrs[l-1])
} else {
    print(-1)
}

第二题

在这里插入图片描述
输入描述:

输入第一行仅包含一个正整数n,表示任意序列的长度。(1<=n<=20000)
输入第二行包含n个整数,表示给出的序列,每个数的绝对值都小于10000。

输出描述:

输出仅包含一个整数,表示最少的操作数量。

输入
5
-1 2 3 10 100
输出
103
let n = parseInt(readline()), count = 0
let arr = readline().split(' ').map(item => parseInt(item))
arr.sort((a,b) => a-b)

for(let i = 1; i <= n; i++) {
    if(arr[i-1] !== i) {
        count += Math.abs(arr[i-1] - i)
    }
}
print(count)

第三题

在这里插入图片描述

输入描述:

第一行输入一个整数T(1<=T<=10),表示数据组数。
每组数据占四行,第一行输入一个整数N(1<=N<=500000);
第二行输入一个长度为N且仅包含数字0、1、2的字符串,第i个数字表示左起第i张餐桌已坐有的用餐人数;
第三行输入一个整数M(1<=M<=2N且保证排队的每个人进入食堂时都有可供选择的餐桌);
第四行输入一个长度为M且仅包含字母M、F的字符串,若第i个字母为M,则排在第i的人为男性,否则其为女性。

输出描述:

每组数据输出占M行,第i行输出一个整数j(1<=j<=N),表示排在第i的人将选择左起第j张餐桌用餐。

输入:
1
5
01102
6
MFMMFF
输出:
2
1
1
3
4
4

直接使用写好的小顶堆

class PriorQueue {
    constructor(mark) {
        this.heap = []
        this.mark = mark
    }
    getParent(index) {
        return Math.floor((index-1)/2)
    }
    getLeft(index) {
        return index * 2 + 1
    }
    getRight(index) {
        return index * 2 + 2
    }
    compare(p, cur) {
        if(this.mark=='min') {
            return p > cur
        } else {
            return p < cur
        }
    }
    swim(index) {
        if(index==0) return
        let parent = this.getParent(index)
        while(parent>=0 && this.compare(this.heap[parent], this.heap[index])) {
            this.swap(parent, index)
            index = parent
            parent = this.getParent(index)
        }
    }
    insert(val) {
        this.heap.push(val)
        this.swim(this.heap.length-1)
    }
    sink(index) {
        let left = this.getLeft(index)
        while(left < this.heap.length) {
            let right = this.getRight(index)
            if(right<this.heap.length && this.compare(this.heap[left], this.heap[right])) left = right
            if(this.compare(this.heap[index], this.heap[left])) {
                this.swap(left, index)
                index = left
                left = this.getLeft(index)
            } else {
                break
            }
        }
    }
    pop() {
        if(this.heap.length == 0) return undefined
        if(this.heap.length == 1) return this.heap.shift()
        let min = this.heap[0]
        this.heap[0] = this.heap.pop()
        this.sink(0)
        return min
    }
    swap(p1, p2) {
        [this.heap[p1], this.heap[p2]] = [this.heap[p2], this.heap[p1]]
    }
    peek() {
        return this.heap[0]
    }
    size() {
        return this.heap.length
    }
}


let team = parseInt(readline())
while(team--) {
    let num = parseInt(readline())
    let s0 = new PriorQueue('min'), s1 = new PriorQueue('min'), s2 = new PriorQueue('min')
    let table = readline()
    for(let index=1; index<=table.length; index++ ){
        let item = table.charAt(index-1)
        if(item=='0') {
            s0.insert(index)
        } else if(item=='1'){
            s1.insert(index)
        } else{
            s2.insert(index)
        }
    }
    let res = []
    let numPeople = parseInt(readline())
    let people = readline()
    for(let i=0; i<people.length; i++) {
        let sex = people.charAt(i)
        if(sex === 'M') {
            if(s1.size()) {
                res.push(s1.peek())
                let out = s1.pop()
                s2.insert(out)
            }else {
                res.push(s0.peek())
                let out = s0.pop()
                s1.insert(out)
                //s1.sort((a,b) => a-b)
            }
        } else {
            if(s0.size()) {
                res.push(s0.peek())
                let out = s0.pop()
                s1.insert(out)
                //s1.sort((a,b) => a-b)
            } else {
                res.push(s1.peek())
                let out = s1.pop()
                s2.insert(out)
            }
        }
    }
    // 不要使用print
    res.forEach(item => console.log(item))
}

第四题 (做不出)

在这里插入图片描述
输入描述:

第一行输入一个整数N(1<=N<=300),表示二叉树的节点数。
第二行输入N个由空格隔开的整数,表示按中序遍历记录下的各个节点的权值,所有权值均为不超过1000的正整数。

输出描述:

输出一个整数,表示最优二叉树的总开销。

输入:
5
7 6 5 1 3
输出:
45

在这里插入图片描述
最优二叉树如图所示,总开销为7 * 1 + 6 * 5 + 5 * 1 + 1 * 3 = 45。

参考:
二叉树通常是递归的思想,主要没弄懂第三个参数root其实是代表上一层的父节点。

首先要明白中序遍历的特点:选取其中一个节点,其左边的节点都是其左子树上的节点,其右边的节点都是其右子树上的节点。

var n = parseInt(readline())
var table = new Array(n).fill(-1).map(item => new Array(n).fill(-1).map(item => new Array(n).fill(-1)))
var weight = readline().split(' ').map(item => parseInt(item))

function dfs(left, right, root) {
    if(left > right) return 0
    if(root>=0 && table[left][right][root]!=-1){
        return table[left][right][root];
    }
    let cost = Number.MAX_VALUE
    for(let i=left; i<=right; i++){
        let leftCost=dfs(left,i-1,i);//左子树开销
        let rightCost=dfs(i+1,right,i);//右子树开销
        //root=-1时为最上面的根节点,已经是根节点了,不能再和父节点相乘计算花销
        cost=Math.min(cost,leftCost + rightCost + weight[i] * (root != -1 ? weight[root] : 0));
    }
    //只有根节点下面的这些节点才能计算花销,因为计算是从子节点往上和其父节点的权值相乘,根节点没法计算
    if(root>=0){
        table[left][right][root]=cost;
    }
    return cost;
}

let result = dfs(0, n-1, -1)
console.log(result)
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值