Blocking Elements
Blocking Elements
题目描述
给定一个长度为
. 。 特别的,定义 ,同时,若 ,则在原式中 一项的值你应当视为 0。
即为:你选择了若干位置,这些位置将原序列分隔成了若干段。代价是你选择的这些位置的元素和与每一段中所有的元素和的最大值。
给定
思路
题目中大概的意思抽象成“最大值的最小值”,我们会想到二分答案。
则设分割后的到的代价不大于
- 选择的断点的元素总和要小于等于
。(条件1) - 相邻的两个断点之间的元素和的最大值要小于等于
。(条件2)
我们设
列出
而我们发现后面的这个式子是可以用单调列队优化成
最后返回dp[n + 1] <= val
即可。
(我们可以添加一个a[n + 1] = 0
的点来处理边界问题)。
#include<iostream>
#include<algorithm>
#include<queue>
#include<deque>
using namespace std;
#define int long long
const int MAXN = 1e5 + 7;
int n,dp[MAXN];
int a[MAXN],pre[MAXN];
int l,r;
deque<int> q;
bool check(int val){
for(int i = 0;i <= n + 1;i++) dp[i] = 0;
q.clear(),q.push_back(0);
for(int i = 1;i <= n + 1;i++){
while(!q.empty() && pre[i - 1] - pre[q.front()] > val){
q.pop_front();
}
dp[i] = a[i] + dp[q.front()];
while(!q.empty() && dp[q.back()] >= dp[i]) q.pop_back();
q.push_back(i);
}
return dp[n + 1] <= val;
}
signed main(){
int _;
cin>>_;
while(_--){
cin>>n;
a[n + 1] = 0;
for(int i = 1;i <= n;i++) cin>>a[i],pre[i] = pre[i - 1] + a[i];
l = 1,r = pre[n];
while(l < r){
int mid = (l + r) / 2;
if(check(mid)) r = mid;
else l = mid + 1;
}
cout<<l<<endl;
}
return 0;
}
本文来自博客园,作者:wyl123ly,转载请注明原文链接:https://www.cnblogs.com/wyl123ly/p/18438348
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!