题意:给定一个长度为n的序列,给定一个k,求上升序列长度为k+1的序列数
思路:dp[i][j]表示到第i个数位置,上升序列长度为j的个数。
dp[i][j] = sum(dp[k][j-1]) (k<i)
直接三重循环复杂度肯定不够
所以考虑用树状数组来优化
#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
typedef long long ll;
const int maxn = 1e5+10;
int a[maxn];
ll dp[maxn][13];
ll lowbit(int x)
{
return x&(-x);
}
void add(ll x,ll y,ll d)
{
while(x<maxn)
{
dp[x][y] += d;
x += lowbit(x);
}
}
ll Sum(ll x,ll y)
{
ll sum = 0;
while(x>0)
{
sum += dp[x][y];
x -= lowbit(x);
}
return sum;
}
int main()
{
int n,k;
scanf("%d%d",&n,&k);
for(int i = 1; i <= n; i++)
{
scanf("%d",&a[i]);
}
k++;
memset(dp,0,sizeof(dp));
for(int i = 1; i <= n; i++)
{
for(int j = 1; j <= min(i+1,k); j++)
{
if(j==1)
{
add(a[i],1,1);
}
else
{
ll temp = Sum(a[i]-1,j-1);
add(a[i],j,temp);
}
}
}
printf("%lld\n",Sum(n,k));
return 0;
}