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;
}

猜你喜欢

转载自www.cnblogs.com/autoint/p/10724663.html