题意:
给定长为n的序列求长度为m的递增子序列有多少个,答案mod123456789
容易想到dp【i】【j】表示长度为i的序列中递增子序列长度为j的个数有多少。
那么dp【i】【j】=sum(dp【k】【j-1】)(1<=k<=i-1)
显然朴素算法复杂度是n^2
对于sum(dp【k】【j】)区间求和我们可以用二维数状数组维护那么nlogn就可以接受
这题对于给出的数据n可能数字很大可以离散化到1~n不影响结果
利用unique 和 low_bound可以巧妙的离散化数据
Code:
#include<bits/stdc++.h>
using namespace std;
#define mod 123456789
#define maxn 10005
int a[maxn],b[maxn],dp[maxn][105];
int n,m,N;
int lowbit(int x){
return x&-x;
}
void add(int x,int v,int len){
for(int i=x;i<=N;i+=lowbit(i))
dp[i][len]=(dp[i][len]+v)%mod;
}
int sum(int x,int len){
int ans=0;
for(int i=x;i;i-=lowbit(i))
ans=(ans+dp[i][len])%mod;
return ans;
}
int main(){
while(scanf("%d%d",&n,&m)!=EOF){
memset(dp,0,sizeof(dp));
for(int i=0;i<n;++i){
scanf("%d",&a[i]);
b[i]=a[i];
}
sort(b,b+n);
N=unique(b,b+n)-b;
for(int i=0;i<n;++i){
int dis=lower_bound(b,b+N,a[i])-b+1;
add(dis,1,1);
for(int j=2;j<=m;++j){
int len=sum(dis-1,j-1);
add(dis,len,j);
}
}
printf("%d\n",sum(N,m));
}
return 0;
}