[HNOI2010]CHORUS 合唱队

题解:

  我们设dp[i][j][0/1]表示最终序列从i到j最后放的是i/j(0/1).
  很显然的转移
  if(h[i]<h[i+1]) dp[i][j][0]=dp[i+1][j][0];
  if(h[i]<h[j]) (dp[i][j][0]+=dp[i+1][j][1])%=mod;
  if(h[j]>h[j-1]) dp[i][j][1]=dp[i][j-1][1];
  if(h[j]>h[i]) (dp[i][j][1]+=dp[i][j-1][0])%=mod;

 1 #include<iostream>
 2 #include<cstdlib>
 3 #include<cstdio>
 4 #include<cmath>
 5 #include<algorithm>
 6 #include<cstring>
 7 #include<queue>
 8 #include<vector>
 9 #include<stack>
10 #include<map>
11 #define RG register
12 #define MAXN 3000010
13 #define LL long long int
14 using namespace std;
15 const int INF=1e9;
16 const int mod=19650827;
17 int n;
18 int h[MAXN];
19 LL dp[1010][1010][2];
20 int main()
21 {
22   freopen("1.in","r" ,stdin);
23   scanf("%d",&n);
24   for(int i=1;i<=n;i++) scanf("%d",&h[i]),dp[i][i][0]=1;
25   for(int len=2;len<=n;len++)
26     for(int i=1;i+len-1<=n;i++)
27       {
28     int j=i+len-1;
29     if(h[i]<h[i+1]) dp[i][j][0]=dp[i+1][j][0];
30     if(h[i]<h[j]) (dp[i][j][0]+=dp[i+1][j][1])%=mod;
31     if(h[j]>h[j-1]) dp[i][j][1]=dp[i][j-1][1];
32     if(h[j]>h[i]) (dp[i][j][1]+=dp[i][j-1][0])%=mod;
33       }
34   printf("%lld\n",(dp[1][n][0]+dp[1][n][1])%mod);
35   return 0;
36 }
时间: 2024-08-04 10:16:35

[HNOI2010]CHORUS 合唱队的相关文章

1996: [Hnoi2010]chorus 合唱队

1996: [Hnoi2010]chorus 合唱队 Time Limit: 4 Sec  Memory Limit: 64 MBSubmit: 1057  Solved: 681[Submit][Status][Discuss] Description Input Output Sample Input 4 1701 1702 1703 1704 Sample Output 8 HINT Source 题解:萌萌哒DP题,其实和我一开始想的暴力方法很接近,基本上就是记忆化暴力,然后转变为循环形

bzoj1196:[Hnoi2010]chorus 合唱队

这数据范围明显的区间dp啊...然而据说二维会wa...那就写三维把... #include<cstdio> #include<cstring> #include<cctype> #include<algorithm> using namespace std; #define rep(i,s,t) for(int i=s;i<=t;i++) #define dwn(i,s,t) for(int i=s;i>=t;i--) #define clr(

BZOJ 1996: [Hnoi2010]chorus 合唱队(dp)

简单的dp题..不能更水了.. --------------------------------------------------------------- #include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #define rep(i,n) for(int i=0;i<n;++i) #define clr(x,c) memset(x,c,sizeof(x

bzoj 1996: [Hnoi2010]chorus 合唱队

Description Input Output Sample Input 4 1701 1702 1703 1704 Sample Output 8 HINT Source 因为只会在区间的两端进行操作,这很容易让我们想到一种区间dp的模型... dp[i][j]表示区间[i,j]已经匹配上了的方案数,因为我们需要知道上一个填的数是什么所以多加一维, dp[i][j][0]表示最后填的数在区间左边,dp[i][j][1]表示最后填的数在区间右边, 这样我们可以确切的知道上一个填的数和当前要填的

BZOJ1996 [Hnoi2010]chorus 合唱队

很容易想到区间DP 然后发现这个区间只和圆序列的最后一个数有关,而原序列的最后一个数只可能是现在区间的头或者尾 令$f[i][j][0/1]$表示在区间$[i, j]$之间,原序列的最后一个数是当前区间的头/尾的总答案数 于是只要讨论$a[i], a[i + 1], a[j - 1], a[j]$之间的关系搞一搞就可以了 1 /************************************************************** 2 Problem: 1996 3 User

【BZOJ1996】【Hnoi2010】chorus 合唱队 动态规划

#include <stdio.h> int main() { puts("转载请注明出处[vmurder]谢谢"); puts("网址:blog.csdn.net/vmurder/article/details/43967361"); } 题解: f[N][N][2]暴力维护即可. 代码:(水得我都不敢测样例就直接交了) #include <cstdio> #include <cstring> #include <iost

【BZOJ1996】【HNOI2010】合唱队 [区间DP]

合唱队 Time Limit: 4 Sec  Memory Limit: 64 MB[Submit][Status][Discuss] Description Input Output Sample Input 4 1701 1702 1703 1704 Sample Output 8 HINT Main idea 给定一个元素两两不相等的目标序列,每次按照给定方式将一个元素加入到序列当中,问得到目标序列的方案有几种.(加元素的方式:如果加的这个元素比上一个加入的元素小的话则放在队头,否则放在队

[HNOI 2010]chorus 合唱队

Description 题库链接 对于一个包含 \(N\) 个整数的数列 \(A\) ,我们可以把它的所有元素加入一个双头队列 \(B\) . 首先 \(A_1\) 作为队列的唯一元素,然后依次加入 \(A_2\sim A_N\) ,如果 \(A_i<A_{i-1}\) 那么从 \(B\) 的左端加入 \(A_i\) ,否则从 \(B\) 的右端加入 \(A_i\) . 给出最终的队列 \(B\) ,求原数列有多少种可能排列.输出答案对 \(19650827\) 取余. \(1\leq N\le

(DP ) bzoj 1996

1996: [Hnoi2010]chorus 合唱队 Time Limit: 4 Sec  Memory Limit: 64 MBSubmit: 1091  Solved: 702[Submit][Status][Discuss] Description Input Output Sample Input 4 1701 1702 1703 1704 Sample Output 8 HINT 区间dp. f[i][j][k]表示区间i到j最后一个放的是i/j(k=0/1)的方案数. 注意f[i][