Luogu P10741 SEERC2020 Fence Job 题解 [ 蓝 ] [ 线性 dp ] [ 观察 ] [ 状态设计优化 ]
Fence Job:不错的观察类 dp 题!
观察
首先不难发现,假设某一段数字
。 。
那么,我们就可以
并且不难发现,我们最后的答案一定是由这些连续段拼接起来的。
dp 设计
因为有了这个连续段性质,所以我们就比较容易 dp 了。
本人一开始用的是
但是实际上这题有更简单的一个状态定义,同样是
这两种 dp 的状态定义的唯一区别就在于一个是限制了这一位必须是
那么预处理每个数能够拓展到的左右端点后直接转移即可:
- 当
,即对应着接着上一个连续段的方案。 - 否则
,即对应着一个元素单独成一个连续段的情况。
最后输出
同时这个显然是可以用类似背包优化一下空间的,时间复杂度是
代码
不优化版本
#include <bits/stdc++.h>
#define fi first
#define se second
#define eb(x) emplace_back(x)
#define pb(x) push_back(x)
#define lc(x) (tr[x].ls)
#define rc(x) (tr[x].rs)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ldb;
using pi=pair<int,int>;
const ll mod=1e9+7;
const int N=5005;
int n,h[N];
ll dp[N][N];
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin>>n;
for(int i=1;i<=n;i++)cin>>h[i];
for(int i=1;i<=n;i++)dp[i][0]=1;
for(int i=1;i<=n;i++)
{
int l=i,r=i;
while(l-1>=1&&h[l-1]>=h[i])l--;
while(r+1<=n&&h[r+1]>=h[i])r++;
for(int j=1;j<=n;j++)
{
dp[i][j]=dp[i-1][j];
if(l<=j&&j<=r)dp[i][j]=(dp[i][j]+dp[i][j-1])%mod;
}
}
cout<<dp[n][n];
return 0;
}
优化版本
#include <bits/stdc++.h>
#define fi first
#define se second
#define eb(x) emplace_back(x)
#define pb(x) push_back(x)
#define lc(x) (tr[x].ls)
#define rc(x) (tr[x].rs)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ldb;
using pi=pair<int,int>;
const ll mod=1e9+7;
const int N=5005;
int n,h[N];
ll dp[N];
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin>>n;
for(int i=1;i<=n;i++)cin>>h[i];
dp[0]=1;
for(int i=1;i<=n;i++)
{
int l=i,r=i;
while(l-1>=1&&h[l-1]>=h[i])l--;
while(r+1<=n&&h[r+1]>=h[i])r++;
for(int j=l;j<=r;j++)dp[j]=(dp[j]+dp[j-1])%mod;
}
cout<<dp[n];
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!