JZOJ4883. 灵知的太阳信仰

解决一个关于质子数和中子数的数组问题,目标是最小化分组后的最大中子数之和。通过使用单调栈和线段树进行优化,将原始O(n^2)的时间复杂度降低到O(nlogn)。

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

题目大意

给定一个n个元素,每个元素有一个质子数ai和中子数bi
先要将这些元素分成若干个连续的段。每段里不能存在质子数相同的元素,这个段的代价就是所有段内元素中子数的最大值。
求最小代价和。

Data Constraint
n100000

题解

fi表示做完前i个位置最小的代价是多少。
显然我们可以枚举上一段的结束位置来转移,这是O(n2)的。
fi=min(fj+max{bj+1..i})
所以我们可以用一个单调栈来计算每个元素作为最大值影响的区间,然后在线段树上维护fi+bi+1的值。

时间复杂度:O(nlogn)

SRC

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std ;

#define N 100000 + 10
struct Note {
    int l , r , v ;
    Note ( int L = 0 , int R = 0 , int V = 0 ) { l = L , r = R , v = V ; }
} S[N] ;
struct Tree {
    int val , del ;
} T[4*N] ;

int a[N] , b[N] , f[N] ;
int Last[N] , Pre[N] , Smax[N] ;
int n , ret ;

void Build( int v , int l , int r ) {
    if ( l == r ) {
        T[v].val = f[l-1] + b[l] ;
        return ;
    }
    int mid = (l + r) / 2 ;
    Build( v + v , l , mid ) ;
    Build( v + v + 1 , mid + 1 , r ) ;
    T[v].val = min( T[v+v].val , T[v+v+1].val ) ;
}

void Update( int v ) {
    if ( !T[v].del ) return ;
    int ls = v + v , rs = v + v + 1 ;
    T[ls].val += T[v].del ;
    T[rs].val += T[v].del ;
    T[ls].del += T[v].del ;
    T[rs].del += T[v].del ;
    T[v].del = 0 ;
}

void Search( int v , int l , int r , int x , int y ) {
    if ( l == x && r == y ) {
        ret = min( ret , T[v].val ) ;
        return ;
    }
    Update(v) ;
    int mid = (l + r) / 2 ;
    if ( y <= mid ) Search( v + v , l , mid , x , y ) ;
    else if ( x > mid ) Search( v + v + 1 , mid + 1 , r , x , y ) ;
    else {
        Search( v + v , l , mid , x , mid ) ;
        Search( v + v + 1 , mid + 1 , r , mid + 1 , y ) ;
    }
    T[v].val = min( T[v+v].val , T[v+v+1].val ) ;
}

void Change( int v , int l , int r , int x , int y , int delta ) {
    if ( l == x && r == y ) {
        T[v].val += delta ;
        T[v].del += delta ;
        return ;
    }
    Update(v) ;
    int mid = (l + r) / 2 ;
    if ( y <= mid ) Change( v + v , l , mid , x , y , delta ) ;
    else if ( x > mid ) Change( v + v + 1 , mid + 1 , r , x , y , delta ) ;
    else {
        Change( v + v , l , mid , x , mid , delta ) ;
        Change( v + v + 1 , mid + 1 , r , mid + 1 , y , delta ) ;
    }
    T[v].val = min( T[v+v].val , T[v+v+1].val ) ;
}

int main() {
    freopen( "array.in" , "r" , stdin ) ;
    freopen( "array.out" , "w" , stdout ) ;
    scanf( "%d" , &n ) ;
    for (int i = 1 ; i <= n ; i ++ ) scanf( "%d%d" , &a[i] , &b[i] ) ;
    for (int i = 1 ; i <= n ; i ++ ) {
        Pre[i] = Last[a[i]] ;
        Last[a[i]] = i ;
        Smax[i] = max( Smax[i-1] , Pre[i] ) ;
    }
    Build( 1 , 1 , n ) ;
    int top = 0 ;
    for (int i = 1 ; i <= n ; i ++ ) {
        Note now = Note( i , i , b[i] ) ;
        while ( top && b[i] > S[top].v ) {
            Change( 1 , 1 , n , S[top].l , S[top].r , b[i] - S[top].v ) ;
            now.l = S[top].l ;
            top -- ;
        }
        S[++top] = now ;
        ret = 0x7FFFFFFF ;
        Search( 1 , 1 , n , Smax[i] + 1 , i ) ;
        if ( i == n ) printf( "%d\n" , ret ) ;
        else Change( 1 , 1 , n , i + 1 , i + 1 , ret ) ;
    }
    return 0 ;
}

以上.

SLAM地图构建与定位算法,含有卡尔曼滤波和粒子滤波器的程序 SLAM算法的技术文档合集(含37篇文档) slam算法的MATLAB源代码,国外的代码 基于角点检测的单目视觉SLAM程序,开发平台VS2003 本程序包设计了一个利用Visual C++编写的基于EKF的SLAM仿真器 Slam Algorithm with data association Joan Solà编写6自由度扩展卡尔曼滤波slam算法工具包 实时定位与建图(SLAM),用激光传感器采集周围环境信息 概率机器人基于卡尔曼滤波器实现实时定位和地图创建(SLAM算法 机器人地图创建新算法,DP-SLAM源程序 利用Matlab编写的基于EKF的SLAM仿真器源码 机器人定位中的EKF-SLAM算法,实现同时定位和地图构建 基于直线特征的slam机器人定位算法实现和优化 SLAM工具箱,很多有价值的SLAM算法 EKF-SLAM算法对运动机器人和周围环境进行同步定位和环境识别仿真 SLAM using Monocular Vision RT-SLAM机器人摄像头定位,运用多种图像处理的算法 slam(simultaneous localization and mapping)仿真很好的入门 SLAM自定位导航的一个小程序,适合初学者以及入门者使用 slam算法仿真 slam仿真工具箱:含slam的matlab仿真源程序以及slam学习程序 移动机器人栅格地图创建,SLAM方法,可以采用多种地图进行创建 SLAM算法程序,来自悉尼大学的作品,主要功能是实现SLAM算法SLAM算法中的EKF-SLAM算法进行改进,并实现仿真程序 SLAM的讲解资料,机器人导航热门方法
### SLAM算法原理 SLAM(Simultaneous Localization and Mapping),即同步定位与建图,是一种让移动机器人在未知环境中运动时能够构建环境地图的同时计算自身位置的技术。其核心目标是在传感器数据的基础上解决两个主要问题:一是机器人的自我定位;二是周围环境的地图构建。 SLAM通常分为三个主要模块:前端、后端和回环检测。前端负责处理原始传感器数据并估计相机或激光雷达的姿态变化,常见的方法包括基于几何的特征点匹配和直接法[^1]。后端则通过优化技术来最小化累积误差,从而提高轨迹估计精度。回环检测用于识别机器人曾经访问过的区域,消除累计漂移效应。 #### 原理概述 - **状态估计**:SLAM的核心在于建立一个数学模型来描述系统的动态特性及其观测关系。该过程可以被看作是一个贝叶斯滤波器的应用实例,在此过程中,系统试图最大化给定所有测量值下的最可能的状态序列。 - **概率推断**:由于存在噪声干扰,SLAM采用概率论作为基础工具之一,利用卡尔曼滤波(Kalman Filter) 或粒子滤波(Particle Filter) 来完成实时的概率推理任务。 - **非线性优化**:对于某些复杂的SLAM变种来说,比如视觉惯导融合VIO(Visual-Inertial Odometry),往往需要用到更高级别的数值求解技巧——例如稀疏束调整(Sparse Bundle Adjustment)[^2]。 --- ### 实现方式 为了更好地理解如何具体实现SLAM算法,下面给出了一段简单的Python伪代码演示基本流程: ```python import numpy as np class SimpleSLAM: def __init__(self): self.map_points = [] # 地图上的关键点集合 self.robot_pose = None # 当前姿态初始化为空 def process_measurement(self, measurement): """ 处理单次测量 """ new_keypoints = extract_features(measurement.image_data) if not self.map_points: # 如果还没有任何已知地标,则将当前帧的关键点加入到全局坐标系中 add_to_map(new_keypoints) matched_pairs = match_with_existing(new_keypoints, self.map_points) updated_pose = estimate_robot_position(matched_pairs) refined_result = optimize_graph(updated_pose, all_observations_so_far()) update_internal_state(refined_result) ``` 以上只是一个非常简化版的例子,实际工程中的SLAM系统远比这段代码要复杂得多,它需要考虑诸如鲁棒性、效率等因素,并且针对不同类型的硬件平台做出相应适配[^3]。 --- ### 动态SLAM的发展趋势 随着研究进展和技术积累,越来越多的研究者开始关注动态环境下运行效果更好的新型SLAM方案设计。这些新方向不仅限于静态结构重建方面的工作,还包括对可变形物体跟踪的支持能力提升等方面的内容。例如DS-SLAM、Dyna-SLAM等就是专门为应对含有大量活动成分的真实世界场景所开发出来的代表性成果。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值