【一本通OJ 1603:绿色通道】题解

题目链接

题目

高二数学《绿色通道》总共有 n 道题目要抄,编号 1n,抄第 i 题要花 ai 分钟。小 Y 决定只用不超过 t 分钟抄这个,因此必然有空着的题。每道题要么不写,要么抄完,不能写一半。下标连续的一些空题称为一个空题段,它的长度就是所包含的题目数。这样应付自然会引起马老师的愤怒,最长的空题段越长,马老师越生气。

现在,小 Y 想知道他在这 t 分钟内写哪些题,才能够尽量减轻马老师的怒火。由于小 Y 很聪明,你只要告诉他最长的空题段至少有多长就可以了,不需输出方案。

思路

由于最长长度和最短时间都不确定。我们可以假设其中一项确定来思考。

考虑二分答案,二分最长空题段。

假设二分当前最长空题段为 k,我们就可以尝试dp处理。

dpi 表示第 i 题做,且前 i 题的最长空题段小于等于 k 时的最短时间,我们可以枚举上一条做了的题,即:

dpi=minmax(j=ik1,0)i1dpj+ai

答案我们可以在 [nk1,n] 里枚举最后一道题的位置,时间复杂度 O(n2logn)

显然,minmax(j=ik1,0)i1dpj 可以用单调队列优化,时间复杂度 O(nlogn)

总结

这是一道二分+单调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;
}

posted @   zhangtingxi  阅读(475)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 清华大学推出第四讲使用 DeepSeek + DeepResearch 让科研像聊天一样简单!
· 实操Deepseek接入个人知识库
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· 易语言 —— 开山篇
点击右上角即可分享
微信分享提示