주어진 시퀀스 길이 N의 기간 \ (\ {A_I \} \) 의 길이 m의 시퀀스 상승 엄격한 요구의 수이다 \ (MOD \는 ^. 9 + 10 7 \) , \ (n \ ^ 제 3 당량 \) .
해결
어려운 설정 생각 \는 (F는 [I]는 [j]가 \) , i 번째의 마지막 위치를 나타내고, j는 LSIS의 길이는, 우리가있다
\ [F [I] [J] = \ sum_ {K = 1, A_I> a_k} ^ {- 1} I F [K] [J-1] \]
테두리 : \ ([. 1]. F [I] = 1, I = 1, 2, ..., N- \) , 나머지가 0 인
답 : (\. \ sum_ = {I} ^ NF 1 [I] [m] \)
이 유의 \ (O (N ^ 3) \) 알고리즘은, 우선 전사 최적화 문제 실제로 정면 찾는 것이다 \ (\ a_k) 미만 (A_I \) \ 프리픽스와 (F)의, 또한, 정렬을주는 것을 고려 그것은 별개의 데이터 구조와 프리픽스 이산 각 쿼리들의 어레이 및 대응하는 프리픽스 위치를 변경하는 (예를 들면, 트리 라인 펜윅 트리)의 설정을 제공하는, 다음하도록 최적화 될 수있다 (O (N ^ 2log을 \ ^ N) \)
참조 코드 :
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define il inline
#define ri register
#define yyb 1000000007
using namespace std;
struct Map{
int a[1001],b[1001],n;
il void prepare(int m,int ar[]){
n=m;
for(ri int i(1);i<=n;++i)
a[i]=ar[i];sort(a+1,a+n+1);
for(ri int i(1);i<=n;++i)b[i]=dfs(ar[i]);
}
il int look(int x){
return b[x];
}
il int dfs(int x){
int l(1),mid,r(n);
while(l<=r){
mid=l+r>>1;
if(x>a[mid])l=mid+1;
else r=mid-1;
}return l;
}
}L;
struct lowbit{
int n,a[1001];
il void prepare(int m){
n=m,memset(a,0,sizeof(a));
}
il void change(int p,int v){
while(p<=n)(a[p]+=v)%=yyb,p+=-p&p;
}
il int ask(int p){
int ans(0);
while(p)(ans+=a[p])%=yyb,p-=-p&p;return ans;
}
}ar;
int a[1001],dp[1001][1001];
il void read(int&),work();
int main(){
int lsy,i;read(lsy);
for(i=1;i<=lsy;++i)printf("Case #%d: ",i),work();
return 0;
}
il void work(){
int n,m;read(n),read(m);
for(int i(1);i<=n;++i)read(a[i]);
L.prepare(n,a),memset(dp,0,sizeof(dp));
for(int i(1);i<=n;++i)dp[i][1]=1;
for(int i,j(2);j<=m;++j){
ar.prepare(n);
for(i=1;i<=n;++i)
dp[i][j]=ar.ask(L.look(i)-1),
ar.change(L.look(i),dp[i][j-1]);
}int ans(0);
for(int i(1);i<=n;++i)(ans+=dp[i][m])%=yyb;
printf("%d\n",ans);
}
il void read(int &x){
x&=0;ri char c;while(c=getchar(),c<'0'||c>'9');
while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c^48),c=getchar();
}