java_1">P2234 [HNOI2002] 营业额统计 java版本
题目描述
Tiger 最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况。
Tiger 拿出了公司的账本,账本上记录了公司成立以来每天的营业额。分析营业情况是一项相当复杂的工作。由于节假日,大减价或者是其他情况的时候,营业额会出现一定的波动,当然一定的波动是能够接受的,但是在某些时候营业额突变得很高或是很低,这就证明公司此时的经营状况出现了问题。经济管理学上定义了一种最小波动值来衡量这种情况:当最小波动值越大时,就说明营业情况越不稳定。
而分析整个公司的从成立到现在营业情况是否稳定,只需要把每一天的最小波动值加起来就可以了。你的任务就是编写一个程序帮助 Tiger 来计算这一个值。
我们定义,一天的最小波动值 = min { ∣ 该天以前某一天的营业额 − 该天营业额 ∣ } \min\{|\text{该天以前某一天的营业额}-\text{该天营业额}|\} min{∣该天以前某一天的营业额−该天营业额∣}。
特别地,第一天的最小波动值为第一天的营业额。
输入格式
第一行为正整数 n n n( n ≤ 32767 n \leq 32767 n≤32767) ,表示该公司从成立一直到现在的天数,接下来的 n n n 行每行有一个整数 a i a_i ai( ∣ a i ∣ ≤ 1 0 6 |a_i| \leq 10^6 ∣ai∣≤106) ,表示第 i i i 天公司的营业额,可能存在负数。
输出格式
输出一个正整数,即每一天最小波动值的和,保证结果小于 2 31 2^{31} 231。
样例 #1
样例输入 #1
6
5
1
2
5
4
6
样例输出 #1
12
提示
结果说明: 5 + ∣ 1 − 5 ∣ + ∣ 2 − 1 ∣ + ∣ 5 − 5 ∣ + ∣ 4 − 5 ∣ + ∣ 6 − 5 ∣ = 5 + 4 + 1 + 0 + 1 + 1 = 12 5+|1-5|+|2-1|+|5-5|+|4-5|+|6-5|=5+4+1+0+1+1=12 5+∣1−5∣+∣2−1∣+∣5−5∣+∣4−5∣+∣6−5∣=5+4+1+0+1+1=12
算法分析
这个问题可以通过维护一个有序集合来解决。我们使用一个 TreeSet
来存储之前所有天的营业额,以便快速找到与当前天营业额最接近的两个值。
- 初始化一个空的
TreeSet
和一个sum
变量来存储最小波动值的总和。 - 对于每一天的营业额,首先检查
TreeSet
是否为空。如果为空,说明是第一天,直接将营业额加到sum
中。 - 如果
TreeSet
不为空,使用floor
方法找到小于等于当前营业额的最大值,使用higher
方法找到大于当前营业额的最小值。 - 计算当前营业额与这两个值的差的绝对值,并选择最小的差值加到
sum
中。 - 将当前营业额添加到
TreeSet
中。
代码实现
java">import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.StreamTokenizer;
import java.util.TreeSet;public class Main {static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));static BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out));static StreamTokenizer st = new StreamTokenizer(in);public static void main(String[] args) throws IOException {st.nextToken();int n = (int) st.nval;TreeSet<Integer> set = new TreeSet<>();int sum = 0;for (int i = 0; i < n; i++) {st.nextToken();int temp = (int) st.nval;if (set.isEmpty()) {sum += temp;} else {Integer a = set.floor(temp);Integer b = set.higher(temp);if (a == null) {sum += b - temp;} else if (b == null) {sum += temp - a;} else {sum += Math.min(temp - a, b - temp);}}set.add(temp);}out.write(Integer.toString(sum));out.flush();}
}
结语
在本题中,我们使用了 TreeSet
来有效地计算每天的最小波动值。这种方法不仅高效,而且代码简洁易懂。希望这篇文章能帮助你理解如何使用数据结构来解决实际问题。如果你有任何问题或建议,请在下方留言。
版权声明:本博客内容为原创,转载请保留原文链接及作者信息。