当前位置: 首页 > news >正文

LG9691

考虑 dp。设 \(f_i\) 表示到位置 \(i\) 所需的最小花费,且第 \(i\) 个位置必选,现在要找上一个决策点 \(j\),这个点应该要在此前所有区间的左端点的后面,才能保证这些区间能被覆盖(即确保至少一个在之前每个区间内),则 \(j\) 应满足 \(\max_{r_k<i}l_k \le j < i\),转移方程 \(f_i=\min_{{\max_{r_k<i}l_k} \le j < i}f_j+a_i\)。左边部分将区间按右端点排序后双指针即可,转移使用单调队列即可。

实现时可以令 \(a_{n+1}=0\),这样 \(f_{n+1}\) 可以直接作为答案输出。时间复杂度 \(O(\sum(n+m\log m))\)

#include<iostream>
#include<cstdio>
#include<algorithm>
#define N 1000010
#define int long long
using namespace std;
int n,m,L,R,a[N],q[N],f[N];
struct line{int l,r;
}c[N];
bool cmp(line x,line y){return x.r<y.r;
}
void solve(){cin>>n;for(int i=1;i<=n;i++)cin>>a[i],f[i]=0;    a[n+1]=0;cin>>m;for(int i=1;i<=m;i++)cin>>c[i].l>>c[i].r;sort(c+1,c+m+1,cmp);int j=1;int mx=0;f[1]=a[1];L=1,R=2;q[L]=0,q[R]=1;for(int i=2;i<=n+1;i++){while(j<=m&&c[j].r<i)mx=max(mx,c[j].l),j++;while(L<=R&&q[L]<mx)L++;f[i]=f[q[L]]+a[i];while(L<=R&&f[q[R]]>=f[i])R--;q[++R]=i;// cout<<q[L]<<' '<<i<<' '<<f[i]<<endl;}cout<<f[n+1]<<'\n';return;
}
signed main(){ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);int T;cin>>T;while(T--)solve();return 0;
}
http://www.wxhsa.cn/company.asp?id=1677

相关文章:

  • 即时通讯小程序 - 实践
  • PHP serialize 序列化完全指南
  • CF2112D
  • CF2112C
  • CF342C
  • ICPC/XCPC 做题记录
  • LG9648
  • LG5689
  • 近五年 CSP NOIP 补题记录
  • CF2111C
  • 唐人日记
  • CF2111B
  • ABC394F
  • LG11793
  • ABC394G
  • MX 炼石 2026 NOIP #5
  • 0126_状态模式(State)
  • Visual Studio 2026 预览体验版现已发布,一起来看看带来哪些新功能!
  • 基于RK3568/RK3576/RK3588/全志H3/飞腾芯片/国产UOS等/国标GB28181监控系统
  • Go语言读写锁(RWMutex)底层原理详解
  • 【GitHub每日速递】无需提示词!Nano Bananary香蕉超市:AI绘画玩法多到停不下来
  • 小题狂练 (J)
  • Drift数据库开发实战:类型安全的SQLite解决方案
  • DELPHI FireDAC连接EXCEL文件
  • 读人形机器人09教育行业
  • PHP判断字符串是否包含中文
  • 当我们红尘作伴,活得潇潇洒洒
  • 诡异的mysql8的问题
  • 二叉树理论
  • 支付中心的熔断降级要怎么做