#P3004. 分奖金(100分)
-
1000ms
Tried: 249
Accepted: 88
Difficulty: 6
所属公司 :
华为od
-
算法标签>栈
分奖金(100分)
题面描述
公司老板进行了一笔大生意,决定通过游戏的方式为每位员工分配奖金。具体规则如下:
- 按照员工的工号顺序,每位员工随机抽取一个数字。
- 对于每位员工,按照工号顺序向后查找,找到第一个数字比自己数字大的员工。
- 如果找到了这样的员工,则当前员工的奖金为“距离 × 数字差值”,其中距离是两个员工工号的差值,数字差值是后一个员工的数字减去当前员工的数字。
- 如果没有找到比自己数字大的员工,则当前员工的奖金为其抽取的随机数字。
思路
这个问题可以类比为“下一个更大元素”(Next Greater Element)问题。我们需要为每个员工找到其后面第一个比自己数字更大的员工,然后根据规则计算奖金。如果找不到,则奖金为自己抽取的数字。
为了高效地解决这个问题,可以使用栈来记录员工的索引。具体步骤如下:
- 初始化一个栈,用于存储员工的索引。
- 从左到右遍历员工列表:
- 当当前员工的数字大于栈顶员工对应的数字时,说明当前员工是栈顶员工的“下一个更大元素”。计算奖金并将栈顶员工弹出。
- 重复上述步骤,直到栈为空或当前员工的数字不大于栈顶员工的数字。
- 将当前员工的索引压入栈中。
- 遍历结束后,栈中剩余的员工找不到更大的数字,奖金即为其随机数字。
cpp
#include <iostream>
#include <vector>
#include <stack>
using namespace std;
int main(){
int n;
// 读取员工数量
cin >> n;
vector<int> nums(n);
// 读取每位员工的随机数字
for(int &num : nums){
cin >> num;
}
// 结果数组,初始化为0
vector<long long> result(n, 0);
// 栈存储员工的索引
stack<int> s;
for(int i = 0; i < n; ++i){
// 当栈不为空且当前数字大于栈顶员工的数字
while(!s.empty() && nums[i] > nums[s.top()]){
int idx = s.top();
s.pop();
// 计算距离和数字差值
long long distance = i - idx;
long long diff = nums[i] - nums[idx];
result[idx] = distance * diff;
}
// 将当前员工的索引压入栈中
s.push(i);
}
// 对于栈中剩余的员工,奖金为其随机数字
while(!s.empty()){
int idx = s.top();
s.pop();
result[idx] = nums[idx];
}
// 输出结果
for(int i = 0; i < n; ++i){
if(i != 0) cout << ' ';
cout << result[i];
}
cout << endl;
return 0;
}
python
# 读取员工数量
n = int(input())
# 读取每位员工的随机数字
nums = list(map(int, input().split()))
# 结果数组,初始化为0
result = [0] * n
# 栈存储员工的索引
stack = []
for i in range(n):
# 当栈不为空且当前数字大于栈顶员工的数字
while stack and nums[i] > nums[stack[-1]]:
idx = stack.pop()
distance = i - idx
diff = nums[i] - nums[idx]
result[idx] = distance * diff
# 将当前员工的索引压入栈中
stack.append(i)
# 对于栈中剩余的员工,奖金为其随机数字
while stack:
idx = stack.pop()
result[idx] = nums[idx]
# 输出结果
print(' '.join(map(str, result)))
java
import java.util.*;
import java.io.*;
public class Main {
public static void main(String[] args) throws IOException{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
// 读取员工数量
int n = Integer.parseInt(br.readLine());
// 读取每位员工的随机数字
String[] parts = br.readLine().split(" ");
int[] nums = new int[n];
for(int i=0;i<n;i++) nums[i] = Integer.parseInt(parts[i]);
// 结果数组,初始化为0
long[] result = new long[n];
// 栈存储员工的索引
Stack<Integer> stack = new Stack<>();
for(int i=0;i<n;i++){
// 当栈不为空且当前数字大于栈顶员工的数字
while(!stack.isEmpty() && nums[i] > nums[stack.peek()]){
int idx = stack.pop();
long distance = i - idx;
long diff = nums[i] - nums[idx];
result[idx] = distance * diff;
}
// 将当前员工的索引压入栈中
stack.push(i);
}
// 对于栈中剩余的员工,奖金为其随机数字
while(!stack.isEmpty()){
int idx = stack.pop();
result[idx] = nums[idx];
}
// 输出结果
StringBuilder sb = new StringBuilder();
for(int i=0;i<n;i++){
if(i > 0) sb.append(' ');
sb.append(result[i]);
}
System.out.println(sb.toString());
}
}
题目内容
公司老板做了一笔大生意,想要给每位员工分配一些奖金,想通过游戏的方式来决定每个人分多少钱。
按照员工的工号顺序,每个人随机抽取一个数字。按照工号的顺序往后排列,遇到第一个数字比自己数字大的,那么,前面的员工就可以获得“距离 ∗ 数字差值”的奖金。如果遇不到比自己数字大的,就给自己分配随机数数量的奖金。
例如,按照工号顺序的随机数字是:2,10,3 。
那么第 2 个员工的数字 10 比第 1 个员工的数字 2 大,所以,第 1 个员工可以获得 1∗(10−2)=8 。
第 2 个员工后面没有比他数字更大的员工,所以,他获得他分配的随机数数量的奖金,就是 10 。
第 3 个员工是最后一个员工,后面也没有比他更大数字的员工,所以他得到的奖金是 3。
请帮老板计算一下每位员工最终分到的奖金都是多少钱。
输入描述
第一行 n 表示员工数量(包含最后一个老板)
第二是每位员工分配的随机数字
输出描述
最终每位员工分到的奖金数量
注:随机数字不重复,员工数量(包含老板)范围 1 ~ 10000,随机数范围 1 ~ 100000
样例1
输入
3
2 10 3
输出
8 10 3