BZOJ1996 [Hnoi2010] 合唱队

Posted _rqy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ1996 [Hnoi2010] 合唱队相关的知识,希望对你有一定的参考价值。

Description

技术分享

Input

技术分享

Output

技术分享

Sample Input

4
1701 1702 1703 1704

Sample Output

8

HINT

技术分享 

Solution

令$f_{i,j}$表示区间$[j,i+j]$在限定最后一个放$i$的情况下的方案数(之所以不是$[j,i]$,是因为那样不好滚动),$g_{i,j}$是限定最后一个放$i+j$的方案数。

转移时考虑上次放的是哪一个就可以了。要特殊处理$i=1$的情况。

代码:

#include <algorithm>
#include <cstdio>
const int N = 1005;
const int mod = 19650827;
int H[N], _f[2][N], _g[2][N];
int main() {
  int n;
  scanf("%d", &n);
  for (int i = 0; i < n; ++i) scanf("%d", &H[i]);
  int *f = _f[0], *g = _g[0], *ff = _f[1], *gg = _g[1];
  for (int i = 0; i < n; ++i) f[i] = 1;
  for (int i = 1; i < n; ++i) { 
    std::swap(f, ff); 
    std::swap(g, gg);
    for (int j = 0; i + j < n; ++j) {
      f[j] = g[j] = 0;
      if (H[j] < H[j + 1]) f[j] += ff[j + 1];
      if (H[j] < H[j + i]) f[j] += gg[j + 1];
      if (H[j + i] > H[j]) g[j] += ff[j];
      if (H[j + i] > H[j + i - 1]) g[j] += gg[j];
      f[j] %= mod;
      g[j] %= mod;
      //printf("%d %d   ", f[j], g[j]);
    }
    //printf("\n");
  }
  printf("%d\n", (f[0] + g[0]) % mod);
  return 0;
}

  


以上是关于BZOJ1996 [Hnoi2010] 合唱队的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ1996[Hnoi2010]chorus 合唱队 区间DP

BZOJ1996HNOI2010合唱队 [区间DP]

BZOJ1996 [Hnoi2010] 合唱队

BZOJ 1996: [Hnoi2010]chorus 合唱队

bzoj 1996: [Hnoi2010]chorus 合唱队

bzoj千题计划211:bzoj1996: [Hnoi2010]chorus 合唱队