1 条题解

  • 0
    @ 2025-12-12 23:27:58

    这是一个完整的 C++ 数据生成器。它会自动生成 1.in/1.out10.in/10.out 共20个文件。

    设计策略 (Coverage Strategy)

    为了保证测试数据的全面性,我设计了以下10个测试点:

    1. 样例数据:题目中给出的演示数据,用于基础验证。
    2. 极小数据N=5,M=5N=5, M=5,方便人工检查。
    3. 全正数:所有元素均为正数,测试累加逻辑。
    4. 全负数:所有元素均为负数,测试负数减法逻辑。
    5. 含零与混合:正负数和0混合,测试 0 对前缀和的影响。
    6. 单点查询 (边界):所有查询满足 L=RL=R,测试是否能正确处理单个元素。
    7. 全区间查询 (边界):所有查询满足 L=1,R=NL=1, R=N,测试最大范围。
    8. 中等规模随机N=1000N=1000,常规随机数据。
    9. 大数据压力测试 1N=105,M=105N=10^5, M=10^5,数值范围大,测试时间复杂度。
    10. 大数据压力测试 2N=105,M=105N=10^5, M=10^5,数值交替波动,测试最大数据量下的稳定性。

    数据生成器代码 (generator.cpp)

    您可以将以下代码保存为 generator.cpp,编译并运行即可。

    #include <iostream>
    #include <fstream>
    #include <vector>
    #include <string>
    #include <random>
    #include <ctime>
    #include <algorithm>
    
    using namespace std;
    
    // ==========================================
    // 1. 标准解法函数 (用于生成 .out 文件)
    // ==========================================
    // 使用 long long 防止溢出,虽然题目数据在 int 范围内,但作为标准解法应具有鲁棒性
    vector<long long> solve(int n, const vector<int>& nums, const vector<pair<int, int>>& queries) {
        // 预处理前缀和,preSum[i] 表示前 i 个数的和
        vector<long long> preSum(n + 1, 0);
        for (int i = 0; i < n; ++i) {
            preSum[i + 1] = preSum[i] + nums[i];
        }
    
        vector<long long> results;
        for (const auto& q : queries) {
            int l = q.first;
            int r = q.second;
            // 查询公式:Sum(L, R) = preSum[R] - preSum[L-1]
            results.push_back(preSum[r] - preSum[l - 1]);
        }
        return results;
    }
    
    // ==========================================
    // 2. 随机数辅助工具
    // ==========================================
    mt19937 rng(time(nullptr)); // 随机数引擎
    
    // 生成 [min, max] 范围内的随机整数
    int random_int(int min, int max) {
        uniform_int_distribution<int> dist(min, max);
        return dist(rng);
    }
    
    // ==========================================
    // 3. 测试点生成逻辑
    // ==========================================
    void generate_test_case(int id) {
        int N, M;
        int min_val, max_val;
        string type_desc; // 用于控制生成逻辑的描述
    
        // 根据 id 设定测试点参数
        switch (id) {
            case 1: // 样例数据
                N = 6; M = 3;
                min_val = -10; max_val = 10;
                break;
            case 2: // 极小数据
                N = 5; M = 5;
                min_val = -100; max_val = 100;
                break;
            case 3: // 全正数
                N = 100; M = 50;
                min_val = 1; max_val = 1000;
                break;
            case 4: // 全负数
                N = 100; M = 50;
                min_val = -1000; max_val = -1;
                break;
            case 5: // 混合含0
                N = 200; M = 100;
                min_val = -100; max_val = 100;
                break;
            case 6: // 大数据 - 单点查询 (L=R)
                N = 100000; M = 100000;
                min_val = -1000; max_val = 1000;
                break;
            case 7: // 大数据 - 全区间查询 (L=1, R=N)
                N = 100000; M = 100000;
                min_val = -1000; max_val = 1000;
                break;
            case 8: // 中等规模随机
                N = 1000; M = 1000;
                min_val = -1000; max_val = 1000;
                break;
            case 9: // 最大规模随机
                N = 100000; M = 100000;
                min_val = -1000; max_val = 1000;
                break;
            case 10: // 最大规模压力测试
                N = 100000; M = 100000;
                min_val = -1000; max_val = 1000;
                break;
            default:
                N = 10; M = 10;
                min_val = 0; max_val = 10;
        }
    
        // --- 生成数组数据 ---
        vector<int> nums;
        if (id == 1) {
            // 样例固定数据
            nums = {-2, 0, 3, -5, 2, -1};
        } else {
            for (int i = 0; i < N; ++i) {
                nums.push_back(random_int(min_val, max_val));
            }
        }
    
        // --- 生成查询数据 ---
        vector<pair<int, int>> queries;
        if (id == 1) {
            // 样例固定查询
            queries = {{1, 3}, {3, 6}, {1, 6}};
        } else {
            for (int i = 0; i < M; ++i) {
                int l, r;
                if (id == 6) { 
                    // 单点查询
                    l = random_int(1, N);
                    r = l;
                } else if (id == 7) { 
                    // 全区间查询
                    l = 1;
                    r = N;
                } else {
                    // 常规随机区间
                    int a = random_int(1, N);
                    int b = random_int(1, N);
                    l = min(a, b);
                    r = max(a, b);
                }
                queries.push_back({l, r});
            }
        }
    
        // --- 写入 .in 文件 ---
        string in_filename = to_string(id) + ".in";
        ofstream fin(in_filename);
        fin << N << " " << M << "\n";
        for (int i = 0; i < N; ++i) {
            fin << nums[i] << (i == N - 1 ? "" : " ");
        }
        fin << "\n";
        for (const auto& q : queries) {
            fin << q.first << " " << q.second << "\n";
        }
        fin.close();
    
        // --- 计算答案并写入 .out 文件 ---
        vector<long long> answers = solve(N, nums, queries);
        string out_filename = to_string(id) + ".out";
        ofstream fout(out_filename);
        for (const auto& ans : answers) {
            fout << ans << "\n";
        }
        fout.close();
    
        cout << "Generated Test Case " << id << ": N=" << N << ", M=" << M << endl;
    }
    
    int main() {
        // 生成 1 到 10 号测试点
        for (int i = 1; i <= 10; ++i) {
            generate_test_case(i);
        }
        cout << "All test cases generated successfully!" << endl;
        return 0;
    }
    

    使用说明

    1. 编译运行: 将上述代码保存为 generator.cpp,使用 g++ 编译:

      g++ generator.cpp -o generator -std=c++11
      

      然后运行:

      ./generator
      

      (Windows 下直接运行 generator.exe)

    2. 生成结果: 运行结束后,当前目录下会出现 1.in, 1.out ... 10.in, 10.out 共20个文件。

    3. 数据格式验证

      • 1.in 的内容应该与题目描述中的样例完全一致。
      • 6.in 里的查询应该都是两个相同的数字(如 5 5)。
      • 9.in10.in 的文件会比较大(因为 N=105N=10^5),这是正常的,用于测试程序的效率。
    4. 上传 OJ: 直接将这些文件打包或逐个上传至您的 Online Judge 系统后台即可。所有 .out 文件均由标准的前缀和算法生成,保证了答案的正确性。

    • 1

    信息

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