【一本通OJ 1603:绿色通道】题解
题目链接
题目
高二数学《绿色通道》总共有 道题目要抄,编号 ,抄第 题要花 分钟。小 Y 决定只用不超过 分钟抄这个,因此必然有空着的题。每道题要么不写,要么抄完,不能写一半。下标连续的一些空题称为一个空题段,它的长度就是所包含的题目数。这样应付自然会引起马老师的愤怒,最长的空题段越长,马老师越生气。
现在,小 Y 想知道他在这 分钟内写哪些题,才能够尽量减轻马老师的怒火。由于小 Y 很聪明,你只要告诉他最长的空题段至少有多长就可以了,不需输出方案。
思路
由于最长长度和最短时间都不确定。我们可以假设其中一项确定来思考。
考虑二分答案,二分最长空题段。
假设二分当前最长空题段为 ,我们就可以尝试dp处理。
设 表示第 题做,且前 题的最长空题段小于等于 时的最短时间,我们可以枚举上一条做了的题,即:
答案我们可以在 里枚举最后一道题的位置,时间复杂度 。
显然, 可以用单调队列优化,时间复杂度 。
总结
这是一道二分+单调dp的模板。
题目问最长能多长,可以考虑二分,成为切入点。
当最长长度确定,dp也很容易可以写出。
超时后也容易发现,式子中可以用单调队列优化,代码不难打。
Code
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define N 500010
int n, m, i, j, k;
int l, r, mid, ans;
int dp[N], a[N], t;
pair<int , int>p;
deque<pair<int, int> >q;
int check(int k) {
q.clear();
p.first=0; p.second=0;
q.push_back(p);
for(i=1; i<=n; ++i) {
dp[i]=q.front().first+a[i];
while(!q.empty() && i-q.front().second>k) q.pop_front();
while(!q.empty() && dp[i]<=q.back().first) q.pop_back();
p.first=dp[i];
p.second=i;
q.push_back(p);
}
ans=0x7fffffffffffffff;
for(i=n-k-1; i<=n; ++i) ans=min(ans, dp[i]);
return ans<=t;
}
signed main() {
scanf("%lld%lld", &n, &t);
for(i=1; i<=n; ++i) scanf("%lld", &a[i]);
l=1, r=n;
while(l<r) {
mid=(l+r)>>1;
if(check(mid)) r=mid;
else l=mid+1;
}
printf("%lld", l);
return 0;
}
本文来自博客园,作者:zhangtingxi,转载请注明原文链接:https://www.cnblogs.com/zhangtingxi/p/15897506.html
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 清华大学推出第四讲使用 DeepSeek + DeepResearch 让科研像聊天一样简单!
· 实操Deepseek接入个人知识库
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· 易语言 —— 开山篇