[刷题笔记] Luogu P3205 [HNOI2010] 合唱队
Analysis
一道分类讨论dp
我们发现本题满足大区间包含小区间,区间之间可以互相推导,符合区间dp。
再看看我们需要记录什么?我们发现哪一个数最后放会影响到决策,所以我们需要记录这一层状态。
形式化地,定义\(f_{l,r}\)表示区间\([l,r]\)\(r\)最后放的方案数,那么同理\(f_{r,l}\)就是区间\([l,r]\)中\(l\)最后放的方案数。
注意,我们这里提到的“最后放”和题目中放到队列最前面队列最后面同理。我们会在接下来的讲解中继续说明,也许在下文您会明白。
同时,我们定义\(a_i\)表示第\(i\)名同学的身高。
定义完状态,接下来我们分类讨论:
-
若\(a_l < a_{l+1}\),显然意味着在区间\([l,r]\)中\(l\)可以放在队列最前面,也就是我们所称的“\(l\)最后放”,故\(f_{r,l}+=f_{r,l+1}\)。这里加上的必须是\(f_{r,l+1}\)也就是\(l+1\)最后放的情况,因为此时\(a_l < a_{l+1}\)也就是\(l\)可以最后放,可以转移。
-
若\(a_l < a_r\)且满足\(l+1 \ne r\)时,有\(f_{r,l}+=f_{l+1,r}\)和\(f_{l,r} += f_{r-1,l}\) 解释一下:当\(a_l < a_r\)成立时,若把\(l\)放在最前面,则和她转移的可以确定的是\(r\)放在最后面,至于\(l\)用\(l+1\)转移即可。同理,若将\(r\)放在最后面,和她转移的可以确定的是\(l\)放在最左边,至于\(r\)用\(r-1\)转移即可。
为什么这里必须要满足\(l+1 \ne r\) 呢?反证:当\(l+1 = r\)时,显然\(f_{l,r}=f_{r,l}=1\),而若用上述判断则\(f_{l,r}=f_{r,l}=2\),因为我们初始化使\(f_{i,i}=1(\forall i \in [1,n])\)
-
若\(a_r > a_{r-1}\) 和第一条同理,若\(r\) 放在队列最后面,也就是\(r\)“最后放”,则和她转移的一定是\(f_{l,r-1}\),也就满足\(f_{l,r}+=f_{l,r-1}\)
至此,分类讨论完毕。我们现在可以回答开始的问题了,\(l\)“最后放”就把\(l\)放到数组第二维去,\(r\)最后放同理。我们发现此类题目转移的关键是要找到“什么不变”“什么变”,例如\(a_l\)最后放,已知\(a_l < a_{l+1}\),则可以和\(a_{l+1}\)“最后放”时进行转移,至于\(r\)不变即可。
最后\(ans = f_{1,n}+f_{n,1}\),我们显然不确定谁先放,所以两者加起来即可。
别忘了取模。
Code
#include <iostream>
#include <cstdio>
#include <algorithm>
#define N 10010
#define mod 19650827
using namespace std;
int n;
int a[N];
int f[N][N];
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
f[i][i] = 1;
}
for(int i=2;i<=n;i++)
{
for(int l = 1;l <= n && l+i-1 <= n ; l++)
{
int r = l + i - 1;
if(a[l] < a[l+1]) f[r][l] += f[r][l+1];
if(a[l] < a[r] && l+1 != r) {f[r][l] += f[l+1][r];f[l][r] += f[r-1][l];}
if(a[r] > a[r-1]) f[l][r] += f[l][r-1];
f[l][r] %= mod;
f[r][l] %= mod;
}
}
cout<<(f[1][n]+f[n][1])%mod<<endl;
return 0;
}
本文作者:SXqwq,转载请注明原文链接:https://www.cnblogs.com/SXqwq/p/17624222.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!