目录
- 绿色通道
- 最大连续和
- 修剪草坪
- 旅行问题
已经讲了好多遍了(2025/1/11,2024/12/21),现在详细捋一下思路
首先上来,最有辨识度的就是“最长”空题段“最小”
就是最大值最小——二分答案
木材加工闻着味就过来了(详见2024/12/28)
但这还和木材加工不太一样,check部分不一样
这里要算的是空mid道题,用t分钟能不能实现
那么在固定空mid道题的情况下,从前往后算最小花费时长
f[i]=min(f[i-1],f[i-2],f[i-3]...f[j]...f[i-mid],f[i-mid-1])<—括号里面共有mid个数
用一个小dp就能解决啦
至于单调队列优化,还是看之前讲的吧
#include<iostream>
using namespace std;
int dp[51000],a[51000],n,t;
int check(int mid)
{
for(int i=1;i<=mid+1;i++)dp[i]=a[i];//单调队列优化后,一个补0就能解决这行
for(int i=mid+2;i<=n;i++)
{
dp[i]=0x3f3f3f3f;
for(int j=i-mid-1;j<=i-1;j++)dp[i]=min(dp[j]+a[i],dp[i]);
}
int ans=0x3f3f3f3f;
for(int i=n-mid;i<=n;i++)ans=min(ans,dp[i]);
return ans<=t;
}
int main()
{
cin>>n>>t;
for(int i=1;i<=n;i++)cin>>a[i];
int l=0,r=n,ans=0x3f3f3f3f;
while(l<=r)
{
int mid=(l+r)/2;
if(check(mid))r=mid-1,ans=mid;
else l=mid+1;
}
cout<<ans<<endl;
return 0;
}
也是讲了好多遍了(发现今天的课和2024/12/21的课一模一样)
计算每一个i之前一段距离之和(a[q[l+1]]+a[q[l+2]]+...+a[i-1]+a[i])
可以直接用a[i]-a[q[l]]计算
每一次a[i]都是固定的
想要让a[i]-a[q[l]]尽可能大,那么a[q[l]]就要尽可能小
所以维护的是a[q[l]]的单调递增,那就要把比新来的更大的删掉
while(l<r&&a[q[r-1]]>a[i])r--;
剩下套模板~~
~~~~~~~
#include<iostream>
using namespace std;
int n,m,a[200010],q[200010];
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
{
int x;
cin>>x;
a[i]=a[i-1]+x;
}
int l=0,r=1,ans=-0x3f3f3f3f;
for(int i=1;i<=n;i++)
{
while(l<r&&q[l]<i-m)l++;
ans=max(ans,a[i]-a[q[l]]);
while(l<r&&a[q[r-1]]>a[i])r--;
q[r++]=i;
}
cout<<ans;
return 0;
}
(好了现在和2024/12/21不一样了)
朴素dp之前写过,这里不写了
这里给一个单调队列优化吧
//https://blog.csdn.net/ybC202444/article/details/127161633
//修建草坪,朴素dp
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1e5 + 5 ;
#define ll long long
ll n,k,a[MAXN],q[MAXN];
ll s[MAXN],dp[MAXN][2];
ll l,r;
// dp[i][0]: 第i个数不要,1-i之间,最大效率;
// dp[i][1]: 第i个数要,1-i之间,最大效率;
int main()
{
cin>>n>>k;
for(ll i=1;i<=n;i++)
{
cin>>a[i];
s[i]=s[i-1]+a[i];
}
l=0,r=0;
q[l]=0,r=1;// 队头插入0编号
//单调队列维护
for(ll i=1;i<=n;i++)
{
while(l<r&&q[l]<i-k)l++;
dp[i][0]=max(dp[i-1][1],dp[i-1][0]);
dp[i][1]=dp[q[l]][0]+s[i]-s[q[l]];//j不要,j+1---i要
//dp[i][1]=(dp[q[l]][0]-s[q[l]]) + s[i]
//f[i]=max/min(g(j))+a[i]
//维护递减: dp[j][0]-s[j]
while(l<r&&dp[q[r-1]][0]-s[q[r-1]]<dp[i][0]-s[i])r--;
q[r++]=i;
}
printf("%lld\n",max(dp[n][1],dp[n][0]));
}
自己没写
作业
标签:12,20,int,ll,mid,2025,MAXN,课堂,dp From: https://www.cnblogs.com/yongshao/p/18682348