【hautoj 1282】ykc想吃好吃的 【循环最大字段和】

ykc委托czl在一条首尾相连的小吃街上购买价值最大的商品。小吃街包含n家店铺,每家店铺的商品价值各不相同。任务是确定连续购买一系列店铺商品所能获得的最大总价值。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述

一天,ykc在学校闲的无聊,于是决定上街买点吃的,ykc很懒,本来就不是很像逛街,于是找来了czl帮他买,这里应该有滑稽,而czl也不愿为ykc买东西吃,但是ykc很强势,非让他去买,呢没办法了,然而czl还有很多事要做,没呢么多时间帮ykc,而这条小吃街又很长,有n家店,n有50000这么大,并且这n家店的商品价值有所不同(要知道,商品的价值可能为负,哈哈,很神奇吧,但是czl肯定不会傻到赔钱,所以你懂的),哇,czl要疯了,他不想逛这么久啊,他还有个毛病,他只会连续的逛若干家店,并且由于这条街的店很多,所以肯定不会是一条直线,换句话说就是首尾相连,即第n家店和第一家店是连在一起的,然而ykc希望czl买的东西价值最大,不然就会不开心,于是他就把艰难的任务交给你了,他真的不想浪费时间,你能帮助他吗?
输入

第1行:小吃街的长度N(2 <= N <= 50000)
第2 - N+1行:N个整数,代表每个店的商品价值 (-10^9 <= S[i] <= 10^9)
输出

czl能买到的最大价值
样例输入

6
-2 11 -4 13 5 -2
样例输出

25
提示

模板
代码

#include<stdio.h>
#define LL long long
#define N 50005
LL max(LL x,LL y)
{
    return x>y?x:y;
}
int arr[N];
int main()
{
    int n;
    while(~scanf("%d",&n)) {
        LL sum, sum_1, sum_2, summax_1, summax_2;
        sum = sum_1 = sum_2 = summax_1 = summax_2 = 0;
        for(int i = 0;i < n; i++) {
            scanf("%d",&arr[i]);
            sum += arr[i];
            sum_1 = max(sum_1,0) + arr[i];
            summax_1 = max(sum_1,summax_1);
        }
        for(int i = 0;i < n; i++) {
            arr[i] = -arr[i];
            sum_2 = max(sum_2,0) + arr[i];
            summax_2 = max(sum_2,summax_2);
        }
        printf("%lld\n",max(summax_1,sum+summax_2));
    }
return 0;
}
<think>我们参考用户提供的详细描述引用内容,特别是引用[1][2]中关于SimOTA的实现细节,来构建SimOTA的核心计算流程。SimOTA的核心包括三个关键部分:候选区域筛选、代价矩阵计算、动态正样本分配。下面我们将逐步展开实现步骤。 ### 1. **候选区域筛选** 首先,我们需要筛选出每个目标框(GT)的正样本候选区域。根据描述,候选区域包括目标框中心邻域(如3x3或5x5网格)以及整个目标框范围内的预测点。具体步骤: - 计算所有预测框与所有GT框的IoU(交并比)。 - 对于每个GT框,筛选出满足以下任一条件的预测框: - 位于目标框中心邻域内(通过网格坐标判断)。 - 与目标框的IoU大于阈值(如0.3)。 ### 2. **代价矩阵计算** 代价矩阵 $C$ 是SimOTA的核心,它由分类代价回归代价加权组成: - **分类代价**:使用二元交叉熵(BCE)损失计算预测类别置信度与真实标签的差异。注意,这里先对置信度预测类别预测的乘积开方(校正数量级)。 - **回归代价**:使用GIoU损失计算预测框与GT框的位置差异。 - **总代价**:$C_{i,j} = \lambda \cdot \text{分类代价} + \text{回归代价}$,其中$\lambda$是权重因子(默认为3)。 ### 3. **动态正样本分配** 为每个GT框动态分配正样本数量: - 计算每个GT框与所有预测框的IoU,取前$k$个($k=10$)最大IoU值。 - 对前$k$个IoU求并取整,得到该GT框的正样本数量 $n_j$。 - 对每个GT框,选择总代价最小的前$n_j$个预测框作为正样本。 - 处理冲突:如果一个预测框被分配给多个GT框,则选择代价最小的那个GT框。 ### 4. **伪代码实现** 下面我们用伪代码描述SimOTA的核心流程: ```python def simota_assignment(predictions, targets): """ predictions: 模型输出,包含框位置(Ykc)、置信度(Ykz)、类别(Ylz)等,形状为 [num_predictions, 4+1+num_classes] targets: GT框列表,每个框包含 [class_id, x_center, y_center, width, height],形状为 [num_targets, 5] """ num_pred = predictions.shape[0] num_targets = targets.shape[0] # 步骤1: 筛选候选区域 candidate_mask = get_candidate_mask(predictions, targets) # 形状 [num_pred, num_targets],布尔矩阵 # 步骤2: 计算代价矩阵 cost_matrix = torch.full((num_pred, num_targets), float('inf')) # 初始化无限大代价 # 仅对候选区域计算代价 for j in range(num_targets): indices = torch.where(candidate_mask[:, j])[0] # 第j个GT框的候选预测索引 if len(indices) == 0: continue # 提取候选预测框 pred_boxes = predictions[indices, :4] # 框位置 [m, 4] pred_cls = predictions[indices, 5:] # 类别预测 [m, num_classes] pred_obj = predictions[indices, 4] # 置信度 [m] # 提取第j个GT框 gt_box = targets[j, 1:5] # [x_center, y_center, width, height] gt_class = targets[j, 0] # 类别标签 # 计算分类置信度: sqrt(obj * cls) cls_conf = torch.sqrt(pred_obj.unsqueeze(1) * pred_cls) # [m, num_classes] # 分类代价: BCE损失 cls_cost = F.binary_cross_entropy(cls_conf, torch.ones_like(cls_conf) * gt_class, reduction='none').sum(dim=1) # [m] # 回归代价: GIoU损失 reg_cost = 1.0 - bbox_giou(pred_boxes, gt_box) # [m] # 总代价 total_cost = 3.0 * cls_cost + reg_cost # [m] # 更新代价矩阵 cost_matrix[indices, j] = total_cost # 对不在中心邻域的候选区域添加惩罚(可选) # 这里省略具体实现,可通过额外掩码标记非中心区域,并增加大常数(如100000) # 步骤3: 动态分配正样本 # 计算每个GT框的IoU矩阵 (仅候选区域) iou_matrix = compute_iou(predictions[:, :4], targets[:, 1:5]) # [num_pred, num_targets] # 初始化分配矩阵 assignment_matrix = torch.zeros((num_pred, num_targets), dtype=torch.bool) # 为每个GT框动态确定正样本数量 for j in range(num_targets): # 获取第j个GT框的候选预测索引 indices = torch.where(candidate_mask[:, j])[0] if len(indices) == 0: continue # 取前k个最大IoU(k=10) topk_iou, _ = iou_matrix[indices, j].topk(k=min(10, len(indices)), dim=0) # 动态数量:对前k个IoU求并取整 n_j = int(topk_iou.sum().clamp(min=1)) # 至少1个 # 选择代价最小的前n_j个预测 _, min_indices = cost_matrix[indices, j].topk(k=n_j, largest=False, dim=0) selected_indices = indices[min_indices] # 标记分配 assignment_matrix[selected_indices, j] = True # 处理冲突:一个预测框只能分配给一个GT框(选择代价最小的GT) for i in range(num_pred): if assignment_matrix[i].sum() > 1: # 找出该预测框被分配的所有GT索引 target_indices = torch.where(assignment_matrix[i])[0] # 选择代价最小的GT min_cost_index = cost_matrix[i, target_indices].argmin() # 只保留最小代价的分配 assignment_matrix[i] = False assignment_matrix[i, target_indices[min_cost_index]] = True # 返回分配结果:assignment_matrix形状为[num_pred, num_targets],True表示正样本 return assignment_matrix ``` ### 关键函数说明: - `get_candidate_mask`: 生成候选区域掩码,判断每个预测框是否在GT框的中心邻域或整个GT框内。 - `bbox_giou`: 计算预测框与GT框的GIoU损失。 - `compute_iou`: 计算两组框之间的IoU矩阵。 ### 注意事项: 1. **中心邻域惩罚**:在代价计算中,对于不在中心邻域的候选预测框,可以添加一个大常数(如100000)以降低其被选为优先样本的概率。 2. **动态数量**:$n_j$ 的计算方法是对前$k$个最大IoU求后取整,确保每个目标框至少有一个正样本。 3. **冲突处理**:一个预测框可能被分配给多个GT框,此时选择代价最小的GT框作为最终分配。 ### 实际应用 在YOLOX中,SimOTA的分配结果用于计算最终的损失函数: - 正样本参与类别损失回归损失计算。 - 负样本(未分配任何GT的预测框)只参与置信度损失计算(如二元交叉熵)。 通过以上流程,SimOTA实现了高效且自适应的正样本分配策略,显著提升了目标检测的精度训练稳定性[^1][^2]。 --- ### 相关问题 1. SimOTA中如何处理一个预测框被分配给多个GT框的情况? 2. 在动态确定正样本数量时,为什么选择前k个IoU的作为分配数量? 3. SimOTA相比固定IoU阈值的分配策略有哪些优势?</think>### SimOTA核心计算流程实现 SimOTA的核心计算流程包括框置信度、类别置信度框位置参数的处理,下面是详细实现步骤(基于YOLOX官方实现): #### 1. **输入数据处理** ```python # 输入参数说明 # pred_boxes: 预测框位置 [B, N, 4] (格式: x1, y1, x2, y2) # pred_scores: 预测置信度 [B, N, 1] # pred_cls: 预测类别 [B, N, num_classes] # gt_boxes: 真实框位置 [B, M, 4] # gt_labels: 真实类别 [B, M] (one-hot格式) ``` #### 2. **计算类别置信度** ```python # 计算完整的类别置信度 (开方校正数量级) cls_scores = torch.sqrt(pred_scores * pred_cls) # [B, N, num_classes] ``` #### 3. **筛选正样本候选区域** ```python def get_candidate_mask(pred_boxes, gt_boxes): """ 生成正样本候选区域的布尔掩码 返回:
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值