https://blog.csdn.net/loy_184548/article/details/50073559←推荐
/**********************
通过离散化 +树状数组 优化
****************************/
#include<bits/stdc++.h>
using namespace std;
const int mod = 1e9+7;
const int maxn = 1e3+60;
int s[maxn];// 最初的数组
int e[maxn];// 排序后的书序
int num[maxn];// 储存 离散化后的位置
int dp[maxn][maxn];
int n, m;
int lowbit(int x)
{
return x&(-x);
}
int add(int x, int y, int k)//
{
while(x <= n)
{
dp[x][y]= (dp[x][y]+k)%mod;
x +=lowbit(x);
}
return 0;
}
int getsum(int x, int y)// 找比x+1 小 递增长度为 y的 个数
{
int res = 0;
while(x > 0)
{
res= (res+dp[x][y])%mod;
x -=lowbit(x);
}
return res;
}
int main()
{
int T;
ios::sync_with_stdio(false);
scanf("%d", &T);
int cnt = 0;
while(T--)
{
cnt++;
memset(dp, 0, sizeof dp);
scanf("%d %d", &n, &m);
for(int i = 1;i <= n;i++)
{
scanf("%d", s+i);
e[i] = s[i];
}
/*************离散化过程******************/
sort(e+1, e+n+1);// 排序
for(int i = 1;i <= n;i++)
{
num[i] = lower_bound(e+1, e+n+1, s[i])-e;// 查找第一个大于等于他的数 所在的位置 , 就是他离散化的后的位置
}
/**************************************/
for(int i = 1;i <= n;i++)// 从1 到n 一个一个压入树状数组 不破坏最初的位置
{
for(int j = 1;j <= min(i,m);j++)
{
if(j == 1)
{
add(num[i], 1, 1);//以i结尾的 递增序列 个数很了然 就是1 , 所以 更新 i结尾 长度为1的序列个数
}
else
{
int tmp = getsum(num[i]-1, j-1);// 先找到 比他小的 递增序列长度为j-1 的个数和
add(num[i], j, tmp);// 更新 以i 结尾 长度为j的递增序列个数
}
}
}
printf("Case #%d: %d\n", cnt, getsum(n, m));// 查询总区间 长度为m的递增序列的个数
}
return 0;
}