1 条题解

  • 0
    @ 2025-12-13 0:21:29

    这是一个完整的 C++ 数据生成器,用于生成“空运物资统计(航班预订统计)”题目的测试数据。

    该生成器包含了一个标准的差分数组解法用于生成正确的 .out 文件,并设计了 10 个测试点,覆盖了从样例、边界情况(单点飞行、全航线预订)到最大规模压力测试的各种场景。

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

    您可以将以下代码保存为 generator.cpp,编译并运行。它将在当前目录下生成 1.in/1.out10.in/10.out

    #include <iostream>
    #include <fstream>
    #include <vector>
    #include <string>
    #include <random>
    #include <ctime>
    #include <algorithm>
    #include <tuple>
    
    using namespace std;
    
    typedef long long ll;
    
    // 预订记录结构: first, last, seats
    struct Booking {
        int l, r, v;
    };
    
    // ==========================================
    // 1. 标准解法函数 (用于生成 .out 文件)
    // ==========================================
    // 使用差分数组算法 O(N+M)
    vector<ll> solve(int n, const vector<Booking>& bookings) {
        // 差分数组,大小开 N+2 以防 r=N 时 r+1 越界
        vector<ll> diff(n + 2, 0);
    
        for (const auto& b : bookings) {
            diff[b.l] += b.v;
            diff[b.r + 1] -= b.v;
        }
    
        vector<ll> result;
        ll current_val = 0;
        for (int i = 1; i <= n; ++i) {
            current_val += diff[i];
            result.push_back(current_val);
        }
        return result;
    }
    
    // ==========================================
    // 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 max_seats;
        string desc;
    
        // 根据 id 设定测试点参数
        // 题目限制: N, M <= 2*10^5, Seats <= 10000
        switch (id) {
            case 1: // 样例数据
                N = 5; M = 3; max_seats = 0; // 这里的范围无效,因为下面会硬编码
                desc = "Sample Case";
                break;
            case 2: // 极小数据
                N = 10; M = 5; max_seats = 100;
                desc = "Small N, Small M";
                break;
            case 3: // 单点修改 (L=R) - 测试最小区间
                N = 1000; M = 1000; max_seats = 1000;
                desc = "Single Point Updates (L=R)";
                break;
            case 4: // 全区间修改 (L=1, R=N) - 测试最大区间
                N = 1000; M = 1000; max_seats = 1000;
                desc = "Full Range Updates (L=1, R=N)";
                break;
            case 5: // 只有一架飞机
                N = 1; M = 1000; max_seats = 1000;
                desc = "N=1 Boundary";
                break;
            case 6: // 很多飞机,很少预订 (稀疏)
                N = 200000; M = 10; max_seats = 10000;
                desc = "Large N, Small M";
                break;
            case 7: // 中等规模随机
                N = 50000; M = 50000; max_seats = 5000;
                desc = "Medium Random";
                break;
            case 8: // 大数据 - 随机区间
                N = 200000; M = 200000; max_seats = 1000;
                desc = "Max Constraints Random";
                break;
            case 9: // 大数据 - 溢出测试 (Seats最大)
                // 2*10^5 * 10000 = 2*10^9, 接近 int 上限,累加后必超 int
                N = 200000; M = 200000; max_seats = 10000;
                desc = "Max Constraints Max Seats (long long check)";
                break;
            case 10: // 大数据 - 后半段集中
                N = 200000; M = 200000; max_seats = 5000;
                desc = "Heavy Load on Second Half";
                break;
            default:
                N = 10; M = 10; max_seats = 100;
        }
    
        vector<Booking> bookings;
    
        // 特殊处理样例数据
        if (id == 1) {
            bookings = { {1, 2, 10}, {2, 3, 20}, {2, 5, 25} };
        } else {
            for (int i = 0; i < M; ++i) {
                int l, r, v;
                v = random_int(1, max_seats);
    
                if (id == 3) { // 单点
                    l = random_int(1, N);
                    r = l;
                } else if (id == 4 || id == 5) { // 全区间 或 N=1
                    l = 1; 
                    r = N;
                } else if (id == 10) { // 后半段集中
                    int half = N / 2;
                    if (half < 1) half = 1;
                    // 80% 的概率落在后半段
                    if (random_int(1, 10) <= 8) {
                        int p1 = random_int(half, N);
                        int p2 = random_int(half, N);
                        l = min(p1, p2);
                        r = max(p1, p2);
                    } else {
                        int p1 = random_int(1, N);
                        int p2 = random_int(1, N);
                        l = min(p1, p2);
                        r = max(p1, p2);
                    }
                } else { // 常规随机
                    int p1 = random_int(1, N);
                    int p2 = random_int(1, N);
                    l = min(p1, p2);
                    r = max(p1, p2);
                }
                bookings.push_back({l, r, v});
            }
        }
    
        // --- 写入 .in 文件 ---
        string in_filename = to_string(id) + ".in";
        ofstream fin(in_filename);
        fin << N << " " << M << "\n";
        for (const auto& b : bookings) {
            fin << b.l << " " << b.r << " " << b.v << "\n";
        }
        fin.close();
    
        // --- 计算答案并写入 .out 文件 ---
        vector<ll> result = solve(N, bookings);
        string out_filename = to_string(id) + ".out";
        ofstream fout(out_filename);
        for (int i = 0; i < N; ++i) {
            fout << result[i] << (i == N - 1 ? "" : " ");
        }
        fout << "\n"; 
        fout.close();
    
        cout << "Generated Case " << id << ": " << desc << " (N=" << N << ", M=" << M << ")" << endl;
    }
    
    int main() {
        // 加速 I/O
        ios::sync_with_stdio(false);
        
        for (int i = 1; i <= 10; ++i) {
            generate_test_case(i);
        }
        cout << "All test cases generated successfully!" << endl;
        return 0;
    }
    

    测试点详细设计说明

    1. Case 1 (Sample): 题目自带的样例,用于基础逻辑验证。
    2. Case 2 (Small Scale): N=10,M=5N=10, M=5。小数据,方便人工排查。
    3. Case 3 (Single Point): L=RL=R。退化为单点修改,验证差分操作 diff[l] += v, diff[l+1] -= v 的正确性。
    4. Case 4 (Full Range): L=1,R=NL=1, R=N。每次都覆盖整个数组,验证边界处理(尤其是 diff[N+1] 是否越界)。
    5. Case 5 (N=1 Boundary): 只有一架飞机。这是 NN 的下界,验证程序是否能处理最小 NN
    6. Case 6 (Sparse): N=2×105,M=10N=2 \times 10^5, M=10。大规模 NN 但操作很少,大部分位置结果为 0,测试大数组的初始化和输出效率。
    7. Case 7 (Medium): N=50000,M=50000N=50000, M=50000。常规的中等规模随机测试。
    8. Case 8 (Max Constraints): N=2×105,M=2×105N=2 \times 10^5, M=2 \times 10^5。最大规模压力测试,验证 O(N+M)O(N+M) 算法的时间效率。
    9. Case 9 (Overflow Check): 最大规模,且座位数均为最大值 (1000010000)。总座位数可能达到 2×105×10000=2×1092 \times 10^5 \times 10000 = 2 \times 10^9,如果累加稍微多一点就会超过 int 上限(21亿),强制要求解题者使用 long long
    10. Case 10 (Skewed Distribution): 后半段区间操作密集。测试在不均匀分布下的正确性。

    使用方法

    1. 保存:将代码保存为 generator.cpp
    2. 编译g++ generator.cpp -o generator -O2
    3. 运行./generator
    4. 结果:当前文件夹下会生成 1.in, 1.out10.in, 10.out。可以直接上传到 OJ 系统。
    • 1

    信息

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