CF1945D 题解
题意简述
个人在排队,每个人有两个属性 。有一个人站在这 个人的后面,他想要进到前 个位置中的任何一个。他可以进行任意次数的以下操作:
- 假设他在位置 ,他可以选择一个 ,和他交换位置。一次交换的费用是
问他达成目标的最小费用是多少。
解法
考虑 dp。
先把 用前缀和维护到 数组。
设 为从队尾换到第 个位置的最小花费,显然有:
初始状态是 。
这么转移是 的,肯定过不了,考虑优化。
先把常数项(和 无关的项)提出:
现在问题就转化为:对于每一个 求一个 ,然后 即可。
显然,这个 可以用后缀最大值维护。
于是我们就 解决了这个问题。
Code
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N=2e5+10,INF=0x3f3f3f3f3f3f3f3f;
int n,m;
int a[N],b[N];
int f[N];
void solve(){
cin>>n>>m;
for(int i=1;i<=n;i++)cin>>a[i];
for(int i=1;i<=n;i++)cin>>b[i];
for(int i=1;i<=n;i++)b[i]+=b[i-1];
f[n+1]=0;
int mn=b[n];
for(int i=n;i>=1;i--){
f[i]=mn+a[i]-b[i];
mn=min(mn,f[i]+b[i-1]);
}
int ans=INF;
for(int i=1;i<=m;i++)ans=min(ans,f[i]);
cout<<ans<<'\n';
memset(f,0,sizeof(int)*n+10);
memset(b,0,sizeof(int)*n+10);
memset(a,0,sizeof(int)*n+10);
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
int t;cin>>t;
while(t--)solve();
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】