3 条题解

  • 0
    @ 2025-12-28 16:04:01
    cpp
    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int MAXN = 200005;
    ll diff[MAXN];
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
        int n, m;
        if (!(cin >> n >> m)) return 0;
        for (int i = 0; i < m; ++i) {
            int l, r, v;
            cin >> l >> r >> v;
            diff[l] += v;
            diff[r + 1] -= v;
        }
        ll current_seats = 0;
        for (int i = 1; i <= n; ++i) {
            current_seats += diff[i];
            cout << current_seats << (i == n ? "" : " ");
        }
        cout << "\n";
        return 0;
    }
    
    • 0
      @ 2025-12-28 15:08:40
      /** 
        * 题目:空运物资统计 (Corporate Flight Bookings) 
        * 知识点:差分数组 (Difference Array) 
        * 时间复杂度:O(N + M) 
        * 空间复杂度:O(N) 
        */ 
       
      #include <iostream> 
      #include <vector> 
      
      using namespace std; 
      
      // 使用 long long 防止累加过程中溢出 
      // 虽然本题 seats <= 10000,但 M 可达 2*10^5,总和可能达到 2*10^9,接近 int 极限 
      // 在 OI 中,涉及"求和"通常无脑上 long long 是比较稳妥的策略 
      typedef long long ll; 
      
      const int MAXN = 200005; 
      // 差分数组,开大一点防止 diff[r+1] 越界 
      ll diff[MAXN]; 
      
      int main() { 
          // 1. IO 优化,加快大量数据的读写速度 
          ios::sync_with_stdio(false); 
          cin.tie(nullptr); 
      
          int n, m; 
          if (!(cin >> n >> m)) return 0; 
      
          // 2. 处理 M 条订单 (构建差分数组) 
          for (int i = 0; i < m; ++i) { 
              int l, r, v; 
              cin >> l >> r >> v; 
      
              // 核心差分操作: 
              // 区间 [l, r] 增加 v 
              // 相当于 diff[l] += v, diff[r+1] -= v 
              diff[l] += v; 
              diff[r + 1] -= v; 
          } 
      
          // 3. 还原原数组 (计算前缀和)并输出 
          // current_seats 相当于前缀和 sum[i] 
          ll current_seats = 0; 
          for (int i = 1; i <= n; ++i) { 
              current_seats += diff[i]; 
              
              // 按照题目要求格式输出 
              cout << current_seats << (i == n ? "" : " "); 
          } 
          cout << "\n"; 
      
          return 0; 
      }
      

      算法思想巧妙:

      差分数组的核心思想是将区间更新转化为两个点的操作:diff[l] += v 和 diff[r+1] -= v 通过前缀和还原原数组,将每次区间更新的时间复杂度从 O(r-l+1) 降低到 O(1) 工程实现考虑周全:

      使用 long long 类型防止累加过程中的整数溢出 数组大小设为 MAXN = 200005,避免 diff[r+1] 操作越界 加入 IO 优化提升大数据量时的读写效率 代码结构清晰:

      三个阶段分明:IO 优化 → 构建差分数组 → 还原并输出 变量命名直观(如 current_seats 清楚表示当前座位数) 注释详细,解释了每个关键步骤的原理 时间复杂度优化显著:

      总体复杂度 O(N+M) 相比暴力法 O(N×M) 在处理大量区间操作时优势明显 特别适用于 N 和 M 都很大的场景

      • 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
        标签
        (无)
        递交数
        3
        已通过
        3
        上传者