CodeForces 1557D :Ezzat and Grid 线段树维护DP

博客讨论了一道竞赛题目,涉及将一定数量的全0段转换为全1段,同时要求至少存在两行有相同列全为1。作者首先尝试贪心算法,但被证明不正确。接着转向动态规划,设计状态转移方程,使用线段树优化查询和修改操作。代码中展示了如何实现这一动态规划和线段树结合的解决方案。

传送门

题意

n n n行全 0 0 0段,将其中 m m m段赋值为 1 1 1,问满足条件的行数最多是多少。条件为:两行至少有一列全 1 1 1

分析

比赛的时候想的是贪心,用线段树 c h e c k check check,赛后直接被辛格 h a c k hack hack
本着贪心不对就往 d p dp dp上考虑的原则,我们考虑一下怎么去设计状态
f i f_i fi为保留第 i i i行的话,最少需要删多少行,假设第 j j j行和第 i i i行符合条件,那么, f [ i ] = f [ j ] + ( i − j − 1 ) f[i] = f[j] + (i - j - 1) f[i]=f[j]+(ij1),转化一下就是 f [ i ] = ( f [ j ] − j ) + ( i − 1 ) f[i] = (f[j] - j) + (i - 1) f[i]=(f[j]j)+(i1),其中跟 j j j相关的部分直接用线段树维护就可以了
因为数据范围比较大,所以需要离散化一下

代码

#pragma GCC optimize(3)
#include <bits/stdc++.h>
#define debug(x) cout<<#x<<":"<<x<<endl;
#define dl(x) printf("%lld\n",x);
#define di(x) printf("%d\n",x);
#define _CRT_SECURE_NO_WARNINGS
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;
typedef vector<int> VI;
const int INF = 0x3f3f3f3f;
const int N = 8e5 + 10;
const ll mod = 1000000007;
const double eps = 1e-9;
const double PI = acos(-1);
template<typename T>inline void read(T &a) {
    char c = getchar(); T x = 0, f = 1; while (!isdigit(c)) {if (c == '-')f = -1; c = getchar();}
    while (isdigit(c)) {x = (x << 1) + (x << 3) + c - '0'; c = getchar();} a = f * x;
}
int gcd(int a, int b) {return (b > 0) ? gcd(b, a % b) : a;}
vector<PII> p[N];
vector<int> nums;
int n, m;
int f[N],pre[N];
bool st[N];

int find(int x) {
    return lower_bound(nums.begin(), nums.end(), x) - nums.begin();
}

struct Node {
    int l, r;
    PII x, add; // f[j] - j,节点编号
} tr[N * 4];

void push(int u){
    tr[u].x = min(tr[u << 1].x,tr[u << 1 | 1].x);
}

void down(int u){
    if(tr[u].add.fi == INF) return;
    tr[u << 1].x = tr[u].add;
    tr[u << 1 | 1].x = tr[u].add;
    tr[u << 1].add = tr[u].add;
    tr[u << 1 | 1].add = tr[u].add;
    tr[u].add = {INF,0};
}

void build(int u, int l, int r) {
    tr[u].l = l, tr[u].r = r, tr[u].x = mp(0, 0), tr[u].add = mp(INF, 0);
    if (l == r) return;
    int mid = (l + r) >> 1;
    build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r);
}

void modify(int u,int l,int r,PII k){
    
    if(tr[u].l >= l && tr[u].r <= r){
        tr[u].x = min(tr[u].x,k);
        tr[u].add = min(tr[u].add,k);
        return;
    }
    down(u);
    int mid = (tr[u].l + tr[u].r) >> 1;
    if(l <= mid) modify(u << 1,l,r,k);
    if(r > mid) modify(u << 1 | 1,l,r,k);
    push(u);
}

PII query(int u,int l,int r){
    if(tr[u].l >= l && tr[u].r <= r){
        return tr[u].x;
    }
    down(u);
    int mid = (tr[u].l + tr[u].r) >> 1;
    PII x = mp(INF,0);
    if(l <= mid) x = query(u << 1,l,r);
    if(r > mid) x = min(query(u << 1 | 1,l,r),x);
    return x;
}

int main() {
    read(n), read(m);
    while (m--) {
        int id, l, r;
        read(id), read(l), read(r);
        p[id].pb(mp(l, r));
        nums.pb(l), nums.pb(r);
    }
    sort(nums.begin(), nums.end());
    nums.erase(unique(nums.begin(), nums.end()), nums.end());
    for (int i = 1; i <= n; i++)
        for (auto &t : p[i]) t.fi = find(t.fi) + 1, t.se = find(t.se) + 1;
    int si = SZ(nums);
    build(1,1,si);
    for(int i = 1;i <= n;i++){
        if(!SZ(p[i])) {f[i] = INF;continue;}
        PII ans = mp(INF,0);
        for(auto t:p[i]) ans = min(ans,query(1,t.fi,t.se));
        f[i] = ans.fi + i - 1,pre[i] = ans.se;
        for(auto t:p[i]) modify(1,t.fi,t.se,mp(f[i] - i,i));
    }
    int ans = INF,id = 0;
    for(int i = 1;i <= n;i++) if(f[i] + n - i < ans) ans = f[i] + n - i,id = i;
    while(id){
        st[id] = true;
        id = pre[id];
    }
    di(ans);
    for(int i = 1;i <= n;i++) if(!st[i]) printf("%d ",i);
    return 0;
}
同步定位与地图构建(SLAM)技术为移动机器人或自主载具在未知空间中的导航提供了核心支撑。借助该技术,机器人能够在探索过程中实时构建环境地图并确定自身位置。典型的SLAM流程涵盖传感器数据采集、数据处理、状态估计及地图生成等环节,其核心挑战在于有效处理定位与环境建模中的各类不确定性。 Matlab作为工程计算与数据可视化领域广泛应用的数学软件,具备丰富的内置函数与专用工具箱,尤其适用于算法开发与仿真验证。在SLAM研究方面,Matlab可用于模拟传感器输出、实现定位建图算法,并进行系统性能评估。其仿真环境能显著降低实验成本,加速算法开发与验证周期。 本次“SLAM-基于Matlab的同步定位与建图仿真实践项目”通过Matlab平台完整再现了SLAM的关键流程,包括数据采集、滤波估计、特征提取、数据关联与地图更新等核心模块。该项目不仅呈现了SLAM技术的实际应用场景,更为机器人导航与自主移动领域的研究人员提供了系统的实践参考。 项目涉及的核心技术要点主要包括:传感器模型(如激光雷达与视觉传感器)的建立与应用、特征匹配与数据关联方法、滤波器设计(如扩展卡尔曼滤波与粒子滤波)、图优化框架(如GTSAM与Ceres Solver)以及路径规划与避障策略。通过项目实践,参与者可深入掌握SLAM算法的实现原理,并提升相关算法的设计与调试能力。 该项目同时注重理论向工程实践的转化,为机器人技术领域的学习者提供了宝贵的实操经验。Matlab仿真环境将复杂的技术问题可视化与可操作化,显著降低了学习门槛,提升了学习效率与质量。 实践过程中,学习者将直面SLAM技术在实际应用中遇到的典型问题,包括传感器误差补偿、动态环境下的建图定位挑战以及计算资源优化等。这些问题的解决对推动SLAM技术的产业化应用具有重要价值。 SLAM技术在工业自动化、服务机器人、自动驾驶及无人机等领域的应用前景广阔。掌握该项技术不仅有助于提升个人专业能力,也为相关行业的技术发展提供了重要支撑。随着技术进步与应用场景的持续拓展,SLAM技术的重要性将日益凸显。 本实践项目作为综合性学习资源,为机器人技术领域的专业人员提供了深入研习SLAM技术的实践平台。通过Matlab这一高效工具,参与者能够直观理解SLAM的实现过程,掌握关键算法,并将理论知识系统应用于实际工程问题的解决之中。 资源来源于网络分享,仅用于学习交流使用,请勿用于商业,如有侵权请联系我删除!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值