P3205 [HNOI2010]合唱队
Posted Jozky86
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P3205 [HNOI2010]合唱队相关的知识,希望对你有一定的参考价值。
题意:
有n个数,然后插入队伍中,如果队列当前为空,则直接插入,然后每次插入和上一次插入的比较,如果大于,插入当前队列的最右侧,如果小于,插入当前队列的最左侧
现在给你一个插入后的队形,问有多少种插入方式?
题解:
我们这样分析,对于区间[l,r],最近一次插入的要么是第l位要么就是第r位
所以我们设f[i][j]表示可以排成理想队列中[i,j]区间,且以最后一个排进去是第i人的初始队列种数。
设g[i][j]表示可以排成理想队列中[i,j]区间,且以最后一个排进去是第j人的初始队列种数。
我们考虑f[i][j],第i位是本次刚插入的,那上一个插入的位置可能是在第i+1位或者是第j位,第i+1位的话就是上一次插入的是最左侧,第j位的话就是上一次插入的是最右侧,所以f[i][j]可以由f[i+1][j]和g[i+][j]得到,前提是a[i]要小于a[i+1],或者a[i]小于a[j],因为第i位插入到最左侧,所以肯定是小于上次插入
同理对g[i][j]也可以推导出相应公式
最终为:
代码:
#include<bits/stdc++.h>
#define debug(a,b) printf("%s = %d\\n",a,b);
typedef long long ll;
using namespace std;
inline int read(){
int s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();//s=(s<<3)+(s<<1)+(ch^48);
return s*w;
}
const int maxn=1e3+9;
const int mod=19650827;
int a[maxn];
int f[maxn][maxn],g[maxn][maxn];
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++)cin>>a[i];
for(int i=1;i<=n;i++)f[i][i]=1;
for(int len=1;len<=n;len++){
for(int i=1;i+len-1<=n;i++){
int j=i+len-1;
if(a[i]<a[i+1])//如果上一次进来的是第i+1位
f[i][j]+=f[i+1][j];
if(a[i]<a[j])//如果上一次进来的是第j位
f[i][j]+=g[i+1][j];
if(a[j]>a[i])//如果上一次进来的是第 i位
g[i][j]+=f[i][j-1];
if(a[j]>a[j-1])//如果上一次进入的是第j-1位
g[i][j]+=g[i][j-1];
f[i][j]%=mod;
g[i][j]%=mod;
}
}
cout<<(f[1][n]+g[1][n])%mod;
return 0;
}
以上是关于P3205 [HNOI2010]合唱队的主要内容,如果未能解决你的问题,请参考以下文章
bzoj 1996: [Hnoi2010]chorus 合唱队