1 条题解

  • 0
    @ 2025-12-13 0:14:27

    这是一个完整的 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>
    
    using namespace std;
    
    typedef long long ll;
    
    struct Operation {
        int l, r, v;
    };
    
    // ==========================================
    // 1. 标准解法函数 (用于生成 .out 文件)
    // ==========================================
    // 使用差分数组算法 O(N+K)
    vector<ll> solve(int n, int k, const vector<Operation>& ops) {
        // 差分数组,大小开 N+2 以防 R=N 时 R+1 越界
        vector<ll> diff(n + 2, 0);
    
        for (const auto& op : ops) {
            diff[op.l] += op.v;
            diff[op.r + 1] -= op.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, K;
        int min_v, max_v;
        string desc;
    
        // 根据 id 设定测试点参数
        switch (id) {
            case 1: // 样例数据
                N = 5; K = 3;
                min_v = 0; max_v = 0; // 这里的范围无效,因为下面会硬编码
                desc = "Sample Case";
                break;
            case 2: // 极小数据
                N = 10; K = 5;
                min_v = -10; max_v = 10;
                desc = "Small N, Small K";
                break;
            case 3: // 单点修改 (L=R)
                N = 100; K = 50;
                min_v = 1; max_v = 100;
                desc = "Single Point Updates (L=R)";
                break;
            case 4: // 全区间修改 (L=1, R=N)
                N = 100; K = 50;
                min_v = -50; max_v = 50;
                desc = "Full Range Updates (L=1, R=N)";
                break;
            case 5: // 全正数累加
                N = 1000; K = 1000;
                min_v = 1; max_v = 1000;
                desc = "All Positive V";
                break;
            case 6: // 全负数累加
                N = 1000; K = 1000;
                min_v = -1000; max_v = -1;
                desc = "All Negative V";
                break;
            case 7: // 混合随机
                N = 5000; K = 5000;
                min_v = -1000; max_v = 1000;
                desc = "Mixed Random";
                break;
            case 8: // 大 N 小 K (稀疏操作)
                N = 100000; K = 10;
                min_v = -1000; max_v = 1000;
                desc = "Large N, Small K";
                break;
            case 9: // 小 N 大 K (密集操作)
                N = 10; K = 100000;
                min_v = -100; max_v = 100;
                desc = "Small N, Large K";
                break;
            case 10: // 最大规模压力测试
                N = 100000; K = 100000;
                min_v = -1000; max_v = 1000;
                desc = "Max Constraints (N=10^5, K=10^5)";
                break;
            default:
                N = 10; K = 10; min_v = 1; max_v = 10;
        }
    
        vector<Operation> ops;
    
        // 特殊处理样例数据
        if (id == 1) {
            ops = { {1, 3, 2}, {2, 4, 3}, {3, 5, -2} };
        } else {
            for (int i = 0; i < K; ++i) {
                int l, r, v;
                v = random_int(min_v, max_v);
    
                if (id == 3) { // 单点
                    l = random_int(1, N);
                    r = l;
                } else if (id == 4) { // 全区间
                    l = 1; 
                    r = N;
                } else { // 随机区间
                    int p1 = random_int(1, N);
                    int p2 = random_int(1, N);
                    l = min(p1, p2);
                    r = max(p1, p2);
                }
                ops.push_back({l, r, v});
            }
        }
    
        // --- 写入 .in 文件 ---
        string in_filename = to_string(id) + ".in";
        ofstream fin(in_filename);
        fin << N << " " << K << "\n";
        for (const auto& op : ops) {
            fin << op.l << " " << op.r << " " << op.v << "\n";
        }
        fin.close();
    
        // --- 计算答案并写入 .out 文件 ---
        vector<ll> result = solve(N, K, ops);
        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 << ", K=" << K << ")" << 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,K=5N=10, K=5。简单的小数据,方便人工排查问题。
    3. Case 3 (Single Point): L=RL=R。退化为单点修改,验证差分操作在区间长度为1时是否正确(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 (All Positive): V>0V > 0。验证数值累加逻辑。
    6. Case 6 (All Negative): V<0V < 0。验证数值相减逻辑。
    7. Case 7 (Mixed): VV 有正有负。验证正负抵消后的结果。
    8. Case 8 (Large N, Small K): N=105,K=10N=10^5, K=10。稀疏操作,大部分元素可能为 0,测试大数组的初始化和输出。
    9. Case 9 (Small N, Large K): N=10,K=105N=10, K=10^5。密集操作,每个点被修改非常多次,测试累加后的数值是否溢出 int(虽然题目保证了范围,但解法应使用 long long 保证鲁棒性)。
    10. Case 10 (Stress Test): N=105,K=105N=10^5, K=10^5。最大规模压力测试,验证算法的时间复杂度是否为 O(N+K)O(N+K)。如果使用暴力 O(NK)O(NK) 解法,此点会超时。

    如何使用

    1. 保存:将代码保存为 generator.cpp
    2. 编译g++ generator.cpp -o generator -O2
    3. 运行./generator (Linux/Mac) 或 generator.exe (Windows)。
    4. 结果:当前文件夹下会生成 1.in/1.out10.in/10.out 共 20 个文件。您可以直接将这些文件打包上传到 OJ(Online Judge)系统的后台作为评测数据。
    • 1

    信息

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