[AGC012F]Prefix Median

题目大意:
  给定一个长度为$2n-1(n\le50)$的数组$a$,可以重排$a$中的元素,生成一个长度为$n$的数组$b$,其中$b_i$为$a_1\sim a_{2i-1}$的中位数。求对于给定的$a$能生成多少种不同的$b$。

思路:
  对$a$进行排序,转化题意。求满足以下3个条件的长度为$n$的数列$b$的个数:
  1.$b_i\in\{a_i,a_{i+1},\ldots,a_{2n-i}\}$;
  2.对于$(i<j)$,不存在$b_i<b_j<b_{i+1}$;
  3.对于$(i<j)$,不存在$b_i>b_j>b_{i+1}$。
  用$f[i][j][k]$表示考虑$b$的第$i$位,比它小的可选数有$j$种,比它大的可选数有$k$种。即可用动态规划求得。
  每次转移设$l=[a_i\ne a_{i-1}],r=[a_{m-i+1}\ne a_{m-i+2}]$,对应条件1,表示当前转移可以新填的数。若$a_i=a_{i-1}$或$a_{m-i+1}=a_{m-i+2}$则说明不会增加新填的数。
  转移1:$f[i-1][j+l][k+r]+=f[i][j][k]$,即当前填的数还是上次的数,但是两边各多出$l$或$r$个可以填。
  转移2:$f[i-1][t][k+r+1]+=f[i][j][k](t<j+l)$,表示若将当前填的数变小,左边还剩$t$个可以填,这里本来填的变成了右边的。
  转移3:$f[i-1][j+l+1][t]+=f[i][j][k](t<k+r)$,表示若将当前填的数变大,右边还剩$t$个可以填,这里本来填的变成了左边的。
  状态$O(n^3)$,转移$O(n)$,时间复杂度$O(n^4)$。

 1 #include<cstdio>
 2 #include<cctype>
 3 #include<algorithm>
 4 inline int getint() {
 5     register char ch;
 6     while(!isdigit(ch=getchar()));
 7     register int x=ch^'0';
 8     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
 9     return x; 
10 }
11 constexpr int mod=1e9+7;
12 constexpr int N=51,M=100;
13 int a[N],f[N][M][M];
14 int main() {
15     const int n=getint(),m=n*2-1;
16     for(register int i=1;i<=m;i++) a[i]=getint();
17     std::sort(&a[1],&a[m]+1);
18     f[n][0][0]=1;
19     for(register int i=n;i>1;i--) {
20         const bool l=a[i]!=a[i-1],r=a[m-i+1]!=a[m-i+2];
21         for(register int j=0;j<=m;j++) {
22             for(register int k=0;k<=m;k++) {
23                 if(!f[i][j][k]) continue;
24                 (f[i-1][j+l][k+r]+=f[i][j][k])%=mod;
25                 for(register int t=0;t<j+l;t++) {
26                     (f[i-1][t][k+r+1]+=f[i][j][k])%=mod;
27                 }
28                 for(register int t=0;t<k+r;t++) {
29                     (f[i-1][j+l+1][t]+=f[i][j][k])%=mod;
30                 }
31             }
32         }
33     }
34     int ans=0;
35     for(register int i=0;i<=m;i++) {
36         for(register int j=0;j<=m;j++) {
37             (ans+=f[1][i][j])%=mod;
38         }
39     }
40     printf("%d\n",ans);
41     return 0;
42 }

 

posted @ 2018-05-21 18:58  skylee03  阅读(297)  评论(0编辑  收藏  举报