1 条题解

  • 0
    @ 2025-12-16 12:06:45

    这是一份完整的C++数据生成器。它会生成 1.in/1.out10.in/10.out 共10组测试数据,能够自动处理文件输出和标准答案生成。

    这份生成器涵盖了题目要求的各种情况:

    • 极小数据N=1N=1
    • 全部相同:所有元素都重复。
    • 全部不同(或尽可能不同):稀疏分布。
    • 大量重复:稠密分布。
    • 大数据压测N=30000N=30000 的各种混合情况。

    使用方法

    1. 将下方代码保存为 generator.cpp
    2. 编译并运行:g++ generator.cpp -o generator && ./generator
    3. 程序运行结束后,当前目录下会出现 20 个文件(10组输入+输出)。

    数据生成器代码 (C++14)

    #include <iostream>
    #include <vector>
    #include <string>
    #include <fstream>
    #include <algorithm>
    #include <random>
    #include <set>
    #include <cassert>
    
    using namespace std;
    
    // ==========================================
    // 标准答案逻辑 (Standard Solution)
    // ==========================================
    // 双指针法,原地去重
    // 为了生成 .out 文件,我们需要模拟题目的输出格式
    // 返回值:pair<去重后的长度, 去重后的数组内容(只截取前k个)>
    pair<int, vector<int>> solve(vector<int> nums) {
        if (nums.empty()) return {0, {}};
        
        int slow = 0;
        for (int fast = 1; fast < nums.size(); fast++) {
            if (nums[fast] != nums[slow]) {
                slow++;
                nums[slow] = nums[fast];
            }
        }
        
        int k = slow + 1;
        vector<int> result;
        for(int i=0; i<k; ++i) {
            result.push_back(nums[i]);
        }
        return {k, result};
    }
    
    // ==========================================
    // 数据生成工具箱
    // ==========================================
    mt19937 rng(1337); // 固定种子以保证每次生成结果一致,便于复现
    
    // 生成 [min, max] 范围内的随机整数
    int randomInt(int min, int max) {
        uniform_int_distribution<int> dist(min, max);
        return dist(rng);
    }
    
    // 生成指定策略的测试数据
    vector<int> generateData(int n, int type) {
        vector<int> nums;
        nums.reserve(n);
        
        if (type == 1) { 
            // 策略1: 完全随机,范围较大
            for(int i=0; i<n; ++i) nums.push_back(randomInt(-10000, 10000));
        }
        else if (type == 2) { 
            // 策略2: 只有极少数几个值,大量重复
            int val = randomInt(-100, 100);
            for(int i=0; i<n; ++i) {
                if (i % (n/5 + 1) == 0) val++; // 偶尔变一下
                nums.push_back(val);
            }
        }
        else if (type == 3) { 
            // 策略3: 几乎不重复(如果范围允许),模拟递增序列
            int start = randomInt(-10000, -5000);
            for(int i=0; i<n; ++i) {
                start += randomInt(0, 2); // 0或1或2的增量
                // 限制在题目范围内
                int val = max(-10000, min(10000, start));
                nums.push_back(val);
            }
        }
        else if (type == 4) { 
            // 策略4: 全部相同
            int val = randomInt(-10000, 10000);
            for(int i=0; i<n; ++i) nums.push_back(val);
        }
        else if (type == 5) {
            // 策略5: 阶梯状,每个数重复 random(1, 10) 次
            int val = -5000;
            int count = 0;
            while(nums.size() < n) {
                int repeat = randomInt(1, 10);
                for(int k=0; k<repeat && nums.size() < n; ++k) {
                    nums.push_back(val);
                }
                val += randomInt(1, 50);
                if (val > 10000) val = 10000;
            }
        }
    
        // 题目关键要求:输入必须是非递减顺序
        sort(nums.begin(), nums.end());
        return nums;
    }
    
    // ==========================================
    // 主生成逻辑
    // ==========================================
    void createTestPoint(int id, int n, int strategy) {
        string inFile = to_string(id) + ".in";
        string outFile = to_string(id) + ".out";
        
        cout << "Generating " << inFile << " (N=" << n << ")... ";
        
        // 1. 生成输入数据
        vector<int> nums = generateData(n, strategy);
        
        // 写入 .in 文件
        ofstream fin(inFile);
        fin << n << "\n";
        for(int i=0; i<n; ++i) {
            fin << nums[i] << (i == n-1 ? "" : " ");
        }
        fin << "\n";
        fin.close();
        
        // 2. 生成输出数据
        auto result = solve(nums);
        
        // 写入 .out 文件
        ofstream fout(outFile);
        fout << result.first << "\n";
        for(int i=0; i<result.first; ++i) {
            fout << result.second[i] << (i == result.first-1 ? "" : " ");
        }
        fout << "\n";
        fout.close();
        
        cout << "Done. (Result Length: " << result.first << ")" << endl;
    }
    
    int main() {
        // 题目范围: N <= 30000, Val [-10000, 10000]
        
        // Test 1: 极小数据边界情况
        createTestPoint(1, 1, 1); 
        
        // Test 2: 小数据,随机
        createTestPoint(2, 10, 1);
        
        // Test 3: 小数据,全部相同
        createTestPoint(3, 20, 4);
        
        // Test 4: 中等数据,高重复率(值域很小)
        createTestPoint(4, 500, 2);
        
        // Test 5: 中等数据,随机
        createTestPoint(5, 1000, 1);
        
        // Test 6: 大数据,阶梯状分布(常见情况)
        createTestPoint(6, 10000, 5);
        
        // Test 7: 最大数据,完全随机分布
        createTestPoint(7, 30000, 1);
        
        // Test 8: 最大数据,全部元素相同(极高重复)
        createTestPoint(8, 30000, 4);
        
        // Test 9: 最大数据,尝试构造尽可能不重复(稠密递增)
        createTestPoint(9, 30000, 3);
        
        // Test 10: 最大数据,值域非常小(例如只有3个数来回变,但因为排序了就是分3块)
        // 复用策略2但N最大
        createTestPoint(10, 30000, 2);
    
        cout << "\nAll 10 test points generated successfully." << endl;
        return 0;
    }
    

    数据点详细说明

    1. 1.in: N=1N=1,测试对单个元素的处理能力(边界)。
    2. 2.in: N=10N=10,简单的随机数据,方便人工调试观察。
    3. 3.in: N=20N=20,所有数字都一样,测试是否能正确压缩为长度1。
    4. 4.in: N=500N=500,数字集中在很少的几个值上,测试去重逻辑的密集触发。
    5. 5.in: N=1000N=1000,标准随机分布。
    6. 6.in: N=10000N=10000,阶梯状数据(如 1 1 2 2 2 3 3 ...),这是有序数组最典型的形态。
    7. 7.in: N=30000N=30000,满数据范围,随机分布,综合性能测试。
    8. 8.in: N=30000N=30000,全部元素相同,大数据的极端情况。
    9. 9.in: N=30000N=30000,模拟近似连续递增的数据(重复极少),测试 slow 指针频繁移动的性能。
    10. 10.in: N=30000N=30000,高重复率的大数据测试。
    • 1

    信息

    ID
    19331
    时间
    1000ms
    内存
    32MiB
    难度
    1
    标签
    (无)
    递交数
    1
    已通过
    1
    上传者