HDU5542 The Battle of Chibi
题意
给出长度为n的序列,问这个序列中有多少个长度为m的单调递增子序列。
\(1\le M\le N\le 1000\)
分析
用F[i,j]表示前j个数构成以Aj为结尾的数列中,长度为i的严格递增子序列有多少个
\[F[i,j]=\sum_{k<j\wedge A_k<A_j}F[i-1,k]
\]
复杂度\(O(mn^2)\)。
观察到决策集合的变化一是只增不减,二是有一个前缀范围,用树状数组维护转移即可。时间复杂度\(O(mn\log n)\)
代码
#include<iostream>
#include<algorithm>
#define rg register
#define il inline
#define co const
template<class T>il T read(){
rg T data=0,w=1;rg char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') w=-1;ch=getchar();}
while(isdigit(ch)) data=data*10+ch-'0',ch=getchar();
return data*w;
}
template<class T>il T read(rg T&x) {return x=read<T>();}
typedef long long ll;
using namespace std;
co int N=1e3+1,INF=0x3f3f3f3f,mod=1e9+7;
int n,m,a[N],b[N],c[N],f[N][N],num;
void add(int x,int y){
for(;x<=n+1;x+=x&-x)
c[x]=(c[x]+y)%mod;
}
int ask(int x){
int ans=0;
for(;x;x-=x&-x)
ans=(ans+c[x])%mod;
return ans;
}
void The_Battle_of_Chibi(){
read(n),read(m);
for(int i=1;i<=n;++i) b[i]=read(a[i]);
sort(b+1,b+n+1);
for(int i=1;i<=n;++i) a[i]=lower_bound(b+1,b+n+1,a[i])-b+1;
a[0]=f[0][0]=1;
for(int i=1;i<=m;++i){
fill(c+1,c+n+2,0);
add(1,f[i-1][0]);
for(int j=1;j<=n;++j){
f[i][j]=ask(a[j]-1);
add(a[j],f[i-1][j]);
}
}
int ans=0;
for(int i=1;i<=n;++i) ans=(ans+f[m][i])%mod;
printf("Case #%d: %d\n",++num,ans);
}
int main(){
for(int t=read<int>();t--;) The_Battle_of_Chibi();
return 0;
}
静渊以有谋,疏通而知事。