【HDOJ5542】The Battle of Chibi

我们定义f[i][j]表示前j个数组成的长度为i的合法序列的个数,那么有

因此我们不难写出朴素dp的代码

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 using namespace std;
 6 typedef long long ll;
 7 int T,n,m,a[1100],ans;
 8 int f[1100][1100];
 9 const int mod=1000000007;
10 inline int read() {
11     int ret=0;
12     int op=1;
13     char c=getchar();
14     while(c<'0'||c>'9') {if(c=='-') op=-1; c=getchar();}
15     while(c<='9'&&c>='0') ret=ret*10+c-'0',c=getchar();
16     return ret*op;
17 }
18 int main() {
19     T=read();
20     for(int t=1;t<=T;t++) {
21         memset(a,0,sizeof(a));
22         memset(f,0,sizeof(f));
23         n=read(); m=read();
24         for(int i=1;i<=n;i++) a[i]=read();
25         f[0][0]=1;
26         a[0]=-(1<<30);
27         ans=0;
28         for(int i=1;i<=m;i++)
29             for(int j=1;j<=n;j++)
30                 for(int k=0;k<j;k++)
31                     if(a[k]<a[j]) f[i][j]=(f[i][j]+f[i-1][k])%mod;
32         for(int i=1;i<=n;i++) ans=(ans+f[m][i])%mod;
33         printf("Case #%d: %d
",t,ans);
34     }
35     return 0;
36 }
TLE Code

然而,这种做法的时间复杂度较大,无法通过本题,因此我们考虑优化。

我们将序列A的值离散化,用num[i]表示i离散化后的值,另外,我们令A0=-∞,num[A0]=1,然后建立树状数组维护即可。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 using namespace std;
 6 inline int read() {
 7     int ret=0;
 8     int op=1;
 9     char c=getchar();
10     while(c<'0'||c>'9') {if(c=='-') op=-1; c=getchar();}
11     while(c<='9'&&c>='0') ret=ret*10+c-'0',c=getchar();
12     return ret*op;
13 }
14 int T,n,m,a[1100],b[1100],num[1100];
15 int f[1100][1100];
16 int sum[1100];
17 const int mod=1000000007;
18 #define lowbit(x) ((-x)&(x))
19 int query(int x) {
20     int ret=0;
21     while(x>0) {
22         ret=(ret+sum[x])%mod;
23         x-=lowbit(x);
24     }
25     return ret;
26 }
27 void add(int x,int val) {
28     while(x<=n) {
29         sum[x]=(sum[x]+val)%mod;
30         x+=lowbit(x);
31     }
32 }
33 int main() {
34     T=read();
35     for(int t=1;t<=T;t++) {
36         memset(a,0,sizeof(a));
37         memset(f,0,sizeof(f));
38         memset(b,0,sizeof(b));
39         memset(num,0,sizeof(num));
40         n=read(); m=read();
41         for(int i=1;i<=n;i++) {
42             a[i]=read();
43             b[i]=a[i];
44         }
45         a[0]=b[n+1]=-(1<<30);
46         sort(b+1,b+n+1+1);
47         for(int i=0;i<=n;i++) num[i]=lower_bound(b+1,b+n+1,a[i])-b;
48         f[0][0]=1;
49         for(int i=1;i<=m;i++) {
50             memset(sum,0,sizeof(sum));
51             add(num[0],f[i-1][0]);
52             for(int j=1;j<=n;j++) {
53                 f[i][j]=query(num[j]-1);
54                 add(num[j],f[i-1][j]);
55             }
56         }
57         int ans=0;
58         for(int i=1;i<=n;i++) ans=(ans+f[m][i])%mod;
59         printf("Case #%d: %d
",t,ans);
60     }
61     return 0;
62 }
AC Code
原文地址:https://www.cnblogs.com/shl-blog/p/10988268.html