目录
第1题
小强有n个养鸡场,第i个养鸡场初始有a[i]只小鸡。与其他养鸡场不同的是,他的养鸡场每天增加k只小鸡,小强每天结束都会在数量最多的养鸡场里卖掉一半的小鸡,假如一个养鸡场有x只鸡,则卖出后只剩下x/2(向下取整)只鸡。问m天后小强的n个养鸡场一共多少只小鸡?
-
输入
第一行输入三个int类型n,m,k(1 <= n,m,k <= 10^6)
第二行输入n个正整数,表示n个养鸡场初始鸡的个数
-
输出
输出一个整数表示鸡的总数
-
示例
输入:
3 3 100
100 200 400
输出:
925
最后几分钟A了,很慌张。要点:
0 每天要选最大值 -> 数据结构使用大顶堆(优先队列)
1 不能去更新队列里面的每个数值(否则必tle),队列里每个数都与实际值相差了i*k (i为天数)
2 每天的最大值出队后 卖掉一半 入队的时候数值计算公式很关键:(max_-i*k)//2
计算公式是怎么来的呢?
出队得到假数值里的max -> 恢复到真数据 -> 减少一半 -> 再减去偏移量(恢复到假数值)
即 ( max_+i*k )//2 - k*i 变换后得到 ( max_ - i*k )//2
画个图解释一下 【队列里每个数都与实际值相差了i*k (i为天数)】
在实现上,由于python只有小顶堆(headq/queue.PriorityQueue),所以去负数来实现选择最大值 即每次入队时取负、 ( max_ - i*k )//2 里的 - i*k 变成 + i*k
import sys
line = sys.stdin.readline().strip()
n, m, k = map(int, line.split())
line = sys.stdin.readline().strip()
a = list(map(int, line.split()))
from queue import PriorityQueue
q = PriorityQueue()
for i in a:
q.put(-i) #入队时都取负
for i in range(1, m + 1):
max_ = q.get()
tmp= (max_ + k * i) // 2 # - i*k 变成 + i*k
q.put(tmp)
print(-sum(q.queue) + n * m * k) #队列里n个假数据都和真数据相差了m*k
长度为n的优先队列,每次维护的复杂度是logn;一共取了m次最大值、修改堆 故时间复杂度为O(mlogn)
第2题
先暴力一手 例子能过 提交一直报错
交完之后发现是没有考虑输入数组为空的情况 导致分母会是0 不过照这次笔试的尿性 就算考虑了八成也是0分 这个题暂时没怎么想
题目描述:
总结
真是慌了神了 因为习惯是每道题先无脑暴力试水 然后两道题一直都是0分 搞得我一直以为自己哪里写错了 光输入改了好几次 最后还是例子没错但提交双0 心态崩了
缓一缓 从暴力想到了几次优化:1使用优先队列 减少每次取max的复杂度 2不能每天都更改队列中所有数值,队列里每个数都与实际值相差了i*k 赶紧根据150=400-250写出了公式max_-(max_+i*k)//2 变换后和前面写的是一致的 最后几分钟A了 幸亏公式一找就找对了 要不然gg 与阿里无缘了 连面试都进不去 可真是太菜太丢人了
tips:
python中headq和queue.PriorityQueue的异同?
1 PriorityQueue保证线程安全 heapq 8星
2 PriorityQueue是对heapq的部分封装 也就是说PriorityQueue就用heapq实现的
参考资料:
https://www.nowcoder.com/discuss/396281?type=1