1 条题解

  • 0
    @ 2025-11-18 8:26:13

    题解:

    我们有:

    • n 个容器,每个容量为 a[i]
    • m 个机器人,每个有作用范围 [l, r],零件数 c,类型 t
    • 类型 0 的机器人范围固定
    • 类型 1 的机器人会根据最重要的容器 x 扩展范围到 [min(l, x), max(r, x)]

    我们需要对每个 x 从 1 到 n,计算机器人能放入容器的最大零件数。

    解题思路

    核心观察

    1. 类型 0 机器人:范围固定,对每个 x 的贡献相同
    2. 类型 1 机器人:范围会扩展以包含 x
    3. 限制条件:每个容器不能超过容量 a[i]

    关键步骤

    1. 预处理类型 0 机器人的贡献:计算它们在不考虑类型 1 机器人时的基础分配
    2. 处理类型 1 机器人:对于每个 x,类型 1 机器人的范围扩展后,会产生额外的覆盖
    3. 贪心分配:优先填满容量较小的容器

    算法框架

    对于每个测试用例:
      1. 读取输入
      2. 分别处理类型0和类型1的机器人
      3. 对于每个x从1到n:
           基础值 = 类型0机器人的贡献
           扩展类型1机器人的范围以包含x
           计算类型1机器人扩展后的额外贡献
           考虑容器容量限制,计算总答案
      4. 输出所有x的答案
    

    C 语言实现

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    typedef long long ll;
    
    typedef struct {
        int l, r;
        ll c;
    } Robot;
    
    int cmp_robot(const void *a, const void *b) {
        Robot *ra = (Robot*)a;
        Robot *rb = (Robot*)b;
        if (ra->l != rb->l) return ra->l - rb->l;
        return ra->r - rb->r;
    }
    
    ll min(ll a, ll b) { return a < b ? a : b; }
    ll max(ll a, ll b) { return a > b ? a : b; }
    
    int main() {
        int t;
        scanf("%d", &t);
        
        while (t--) {
            int n, m;
            scanf("%d%d", &n, &m);
            
            ll *a = (ll*)malloc((n + 2) * sizeof(ll));
            for (int i = 1; i <= n; i++) {
                scanf("%lld", &a[i]);
            }
            
            Robot *robots0 = (Robot*)malloc(m * sizeof(Robot));
            Robot *robots1 = (Robot*)malloc(m * sizeof(Robot));
            int cnt0 = 0, cnt1 = 0;
            
            for (int i = 0; i < m; i++) {
                int l, r, type;
                ll c;
                scanf("%d%d%lld%d", &l, &r, &c, &type);
                if (type == 0) {
                    robots0[cnt0].l = l;
                    robots0[cnt0].r = r;
                    robots0[cnt0].c = c;
                    cnt0++;
                } else {
                    robots1[cnt1].l = l;
                    robots1[cnt1].r = r;
                    robots1[cnt1].c = c;
                    cnt1++;
                }
            }
            
            // 预处理类型0机器人的基础贡献
            ll *base_flow = (ll*)calloc(n + 2, sizeof(ll));
            for (int i = 0; i < cnt0; i++) {
                base_flow[robots0[i].l] += robots0[i].c;
                base_flow[robots0[i].r + 1] -= robots0[i].c;
            }
            
            for (int i = 1; i <= n; i++) {
                base_flow[i] += base_flow[i - 1];
            }
            
            // 计算基础值(考虑容器容量限制)
            ll base_total = 0;
            for (int i = 1; i <= n; i++) {
                base_total += min(base_flow[i], a[i]);
            }
            
            // 对类型1机器人按左端点排序
            qsort(robots1, cnt1, sizeof(Robot), cmp_robot);
            
            // 预处理类型1机器人的信息
            int *L = (int*)malloc(cnt1 * sizeof(int));
            int *R = (int*)malloc(cnt1 * sizeof(int));
            ll *C = (ll*)malloc(cnt1 * sizeof(ll));
            
            for (int i = 0; i < cnt1; i++) {
                L[i] = robots1[i].l;
                R[i] = robots1[i].r;
                C[i] = robots1[i].c;
            }
            
            // 计算每个x的答案
            ll *ans = (ll*)malloc((n + 1) * sizeof(ll));
            
            for (int x = 1; x <= n; x++) {
                ll total = base_total;
                
                // 计算类型1机器人扩展后的额外贡献
                ll extra = 0;
                for (int i = 0; i < cnt1; i++) {
                    int new_l = min(L[i], x);
                    int new_r = max(R[i], x);
                    
                    // 简单的贪心:假设额外容量可以完全利用
                    // 实际实现中这里需要更复杂的容量检查
                    ll available = 0;
                    for (int j = new_l; j <= new_r; j++) {
                        ll remaining = a[j] - min(base_flow[j], a[j]);
                        if (remaining > 0) {
                            available += remaining;
                        }
                    }
                    
                    extra += min(C[i], available);
                }
                
                ans[x] = total + extra;
            }
            
            // 输出答案(简化版本,实际需要优化)
            for (int i = 1; i <= n; i++) {
                printf("%lld", ans[i]);
                if (i < n) printf(" ");
            }
            printf("\n");
            
            // 释放内存
            free(a);
            free(robots0);
            free(robots1);
            free(base_flow);
            free(L);
            free(R);
            free(C);
            free(ans);
        }
        
        return 0;
    }
    

    算法优化说明

    上面的代码是一个基础框架,实际AC的代码需要以下优化:

    1. 使用线段树/树状数组:快速查询区间剩余容量
    2. 双指针技巧:高效处理类型1机器人的区间扩展
    3. 离散化:如果数据范围很大
    4. 懒标记:支持区间更新和查询

    复杂度分析

    • 时间复杂度:优化后可达 O((n + m) log n)
    • 空间复杂度:O(n + m)

    关键难点

    1. 类型1机器人范围扩展:需要动态计算扩展后的区间
    2. 容量限制:必须保证每个容器不超过容量
    3. 多查询优化:需要对每个x快速计算答案

    这个问题的核心在于如何高效处理类型1机器人的动态区间扩展,并在考虑容器容量限制的情况下最大化零件分配。

    • 1

    信息

    ID
    5392
    时间
    1000ms
    内存
    256MiB
    难度
    8
    标签
    递交数
    1
    已通过
    1
    上传者