1 条题解

  • 0
    @ 2025-12-5 11:28:12

    这是一个完整的 OI 风格数据生成器(Data Generator)。这段代码会利用**标准解法(Standard Solution)**作为核心逻辑,自动生成 1.in/1.out10.in/10.out 共 20 个文件。

    数据生成策略设计

    为了保证测试数据的强度和覆盖面,设计了以下 10 个测试点:

    • #1 (极小数据)N=5N=5,用于肉眼检查。
    • #2 (小规模随机)N=100N=100,普通随机。
    • #3 (全部相等)N=1000N=1000,所有元素值相同(边界:答案应全为 -1)。
    • #4 (严格单调递增)N=2000N=2000,类似 1 2 3 ... N(边界:环形特性的基本测试)。
    • #5 (严格单调递减)N=2000N=2000,类似 N ... 3 2 1(边界:所有非最大值的下一个更大元素都是首元素)。
    • #6 (大波浪)N=50000N=50000,数值在 1 到 100 之间波动(测试重复数值处理)。
    • #7 (大规模随机)N=105N=10^5,数值范围 10910^9(常规压力测试)。
    • #8 (大规模随机)N=105N=10^5,同上,验证随机性。
    • #9 (极端峰值)N=105N=10^5,只有一个极大值,其余极小(测试栈的弹出性能)。
    • #10 (锯齿波)N=105N=10^5,大小交替 10 1000 10 1000...(最坏情况之一,频繁入栈出栈)。

    Generator 代码 (C++14)

    请将以下代码保存为 gen.cpp,编译并运行即可在当前目录下生成所有测试数据文件。

    #include <bits/stdc++.h>
    using namespace std;
    
    // ==========================================
    // Part 1: 标准解答 (Standard Solution)
    // 用于生成 .out 文件
    // ==========================================
    vector<int> solve(int n, const vector<int>& nums) {
        vector<int> res(n, -1);
        stack<int> s;
        // 2*n - 1 倒序遍历,模拟环形
        for (int i = 2 * n - 1; i >= 0; --i) {
            int realIndex = i % n;
            while (!s.empty() && s.top() <= nums[realIndex]) {
                s.pop();
            }
            if (i < n) {
                if (!s.empty()) {
                    res[realIndex] = s.top();
                } else {
                    res[realIndex] = -1;
                }
            }
            s.push(nums[realIndex]);
        }
        return res;
    }
    
    // ==========================================
    // Part 2: 数据生成器工具 (Generator Tools)
    // ==========================================
    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
    
    // 生成 [L, R] 范围内的随机整数
    int random_int(int L, int R) {
        return uniform_int_distribution<int>(L, R)(rng);
    }
    
    // 生成指定模式的数据
    vector<int> generate_data(int case_id) {
        int n;
        vector<int> a;
    
        switch (case_id) {
            case 1: // 极小数据,便于手算验证
                n = 5;
                for(int i=0; i<n; i++) a.push_back(random_int(1, 10));
                break;
                
            case 2: // 小规模随机
                n = 100;
                for(int i=0; i<n; i++) a.push_back(random_int(1, 1000));
                break;
                
            case 3: // 全部相等 (边界情况)
                n = 1000;
                {
                    int val = random_int(1, 1000);
                    for(int i=0; i<n; i++) a.push_back(val);
                }
                break;
                
            case 4: // 严格单调递增 (测试环形逻辑)
                n = 2000;
                for(int i=0; i<n; i++) a.push_back(i + 1);
                break;
                
            case 5: // 严格单调递减 (测试环形回绕)
                n = 2000;
                for(int i=0; i<n; i++) a.push_back(n - i);
                break;
                
            case 6: // 大规模,小数值范围 (大量重复元素)
                n = 50000;
                for(int i=0; i<n; i++) a.push_back(random_int(1, 50));
                break;
                
            case 7: // 最大规模随机 A
                n = 100000;
                for(int i=0; i<n; i++) a.push_back(random_int(1, 1000000000));
                break;
                
            case 8: // 最大规模随机 B
                n = 100000;
                for(int i=0; i<n; i++) a.push_back(random_int(1, 1000000000));
                break;
                
            case 9: // 只有一个峰值 (其余都很小)
                n = 100000;
                for(int i=0; i<n; i++) a.push_back(random_int(1, 100));
                a[random_int(0, n-1)] = 1000000000; // 插入一个极大值
                break;
                
            case 10: // 锯齿波 (大小交替,考验栈的频繁操作)
                n = 100000;
                for(int i=0; i<n; i++) {
                    if (i % 2 == 0) a.push_back(10);
                    else a.push_back(100000);
                }
                break;
                
            default:
                n = 10;
                for(int i=0; i<n; i++) a.push_back(i);
        }
        return a;
    }
    
    // ==========================================
    // Part 3: 主程序
    // ==========================================
    int main() {
        // 循环生成 1 到 10 号测试点
        for (int i = 1; i <= 10; ++i) {
            string in_file_name = to_string(i) + ".in";
            string out_file_name = to_string(i) + ".out";
    
            cout << "Generating Case " << i << "..." << endl;
    
            // 1. 生成数据
            vector<int> data = generate_data(i);
            int n = data.size();
    
            // 2. 写入 .in 文件
            ofstream fin(in_file_name);
            fin << n << "\n";
            for (int k = 0; k < n; ++k) {
                fin << data[k] << (k == n - 1 ? "" : " ");
            }
            fin << "\n";
            fin.close();
    
            // 3. 计算答案并写入 .out 文件
            vector<int> ans = solve(n, data);
            
            ofstream fout(out_file_name);
            for (int k = 0; k < n; ++k) {
                fout << ans[k] << (k == n - 1 ? "" : " ");
            }
            fout << "\n";
            fout.close();
        }
    
        cout << "All 10 test cases generated successfully." << endl;
        return 0;
    }
    

    使用说明

    1. 环境准备:确保你有 C++ 编译器(如 g++)。
    2. 编译g++ gen.cpp -o gen -std=c++14 -O2
    3. 运行
      • Windows: gen.exe
      • Linux/Mac: ./gen
    4. 结果
      • 程序运行结束后,你的文件夹里会出现 1.in, 1.out ... 10.in, 10.out
      • 你可以直接将这些文件压缩上传到 OJ 后台(如 Hydro, Luogu 等)。

    检查点验证

    • Case 3 (All Equal): 打开 3.out,内容应该全是 -1
    • Case 4 (Sorted Asc): 打开 4.out,例如 1 2 3,输出应为 2 3 -1
    • Case 5 (Sorted Desc): 打开 5.out,例如 3 2 1,输出应为 -1 3 3
    • Case 10 (Sawtooth): 锯齿波能有效检测程序在极端波动下的鲁棒性。

    这套数据生成器完全覆盖了题目所需的各类情况。

    • 1

    信息

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