A. 罚款统计

内存限制:800 MiB 时间限制:3000 ms 输入文件:in 输出文件:out
题目类型:传统 评测方式:文本比较

题目描述

江苏省政府要统计下近期省内的罚款数据,有两个需求:

  1. 按人员id升序统计每人缴纳的罚款总额。取所有id中间的那个。一共x个人交过罚款,就取下标为x/2的人的id。

  2. 统计缴纳罚款金额的中位数(简化下,只需要下标为x/2的即可,不需要考虑偶数个数求中位数的求平均的情况)。

输入格式

大端模式的byte文件,全按int读即可。 如00000001表示1,0000000a表示10,00bc4ff2表示12341234 。

第一个int表示记录的条数,后面的int表示缴纳罚款的人的id,罚款金额,乱序。

输出格式

两行结果,均为int

样例

输入:

如5 1 20 9 200 111222333 100086 1 50 8 300

表示一共5条记录,id为1的人交了20块罚款,9交了200块罚款...

输出:

9

300

第一步的结果为

1,70;

8,300;

9,200;

111222333,100086;

4/2 = 2

输出第三个id 9

罚款中位数为排序后第三个数 300

import java.io.IOException;
import java.io.PrintStream;
import java.io.RandomAccessFile;
import java.nio.IntBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
//示例代码,应该会比较慢吧,本题采用文件io接口,可以直接new File("in"),new File("out")这样调用
public class Main {
    public static void main(String[] args) throws Exception {
        RandomAccessFile fs = new RandomAccessFile("in", "r");
        FileChannel fc = fs.getChannel();
        MappedByteBuffer buffer = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size());
        IntBuffer intBuffer = buffer.asIntBuffer();
        PrintStream stream = new PrintStream("out");
        int size = intBuffer.get();
        hashGroup(intBuffer, stream, size);
        fc.close();
        stream.close();
    }

    public static void hashGroup( IntBuffer intBuffer, PrintStream stream, int size) throws IOException {
        long t = System.currentTimeMillis();
        Map<Integer, Integer> map = new HashMap<>();
        for (int i = 0; i < size; i++) {
            int id = intBuffer.get();
            int fee = intBuffer.get();
            Integer value = map.get(id);
            value = value == null ? fee : value + fee;
            map.put(id, value);
        }
        List<Integer> keys = new ArrayList<>();
        List<Integer> values = new ArrayList<>();
        for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
            keys.add(entry.getKey());
            values.add(entry.getValue());
        }
        Collections.sort(keys);
        Collections.sort(values);
        stream.println(keys.get(keys.size() / 2));
        stream.println(values.get(values.size() / 2));

    }
}

数据范围与提示

人员id是国家统一认证的缴纳罚款人的id,id的范围大约与中国人口数量相当,即【0,15亿】,罚款金额都是整数,有罚站街指挥交通但是罚款金额0的,有骑电动车带人罚20的,也有超速违停罚几百上千的,还有偷税漏税罚款几百万的,总罚款没有超过20亿的。