题意翻译
题目描述
输入一个1~n的排列, 以及一个正整数k, 求该排列种有多少个长度为k+1的上升子序列. 保证答案小于8乘10的18次方.
输入格式
第一行输入两个正整数n和k
接下来n行每行一个正整数描述输入的排列
输出格式
输出一个数表示答案.
题目描述
For the given sequence with nn different elements find the number of increasing subsequences with k+1k+1 elements. It is guaranteed that the answer is not greater than 8·10^{18}8⋅1018 .
输入输出格式
输入格式:
First line contain two integer values nn and kk (1<=n<=10^{5},0<=k<=10)(1<=n<=105,0<=k<=10) — the length of sequence and the number of elements in increasing subsequences.
Next nn lines contains one integer a_{i}ai ( 1<=a_{i}<=n1<=ai<=n ) each — elements of sequence. All values a_{i}aiare different.
输出格式:
Print one integer — the answer to the problem.
输入输出样例
输入样例#1: 复制
5 2 1 2 3 5 4
输出样例#1: 复制
7
跟HDOJ5542-The Battle of Chibi【树状数组优化dp】(推荐,详细介绍)一样,只不过数据范围大一点,注意一下dp的大小就行
#include<stdio.h>
#include<string>
#include<string.h>
#include<cstdio>
#include<algorithm>
#include<iostream>
using namespace std;
typedef long long ll;
const int MAXN=100000+5;//最大元素个数
const int mod=1e9+7;
ll m,n;//元素个数
ll c[MAXN];
ll a[MAXN],b[MAXN],dp[15][MAXN];//c[i]==A[i]+A[i-1]+...+A[i-lowbit(i)+1]
//返回i的二进制最右边1的值
int lowbit(int i)
{
return i&(-i);
}
//返回A[1]+...A[i]的和
ll sum(int x){
ll sum = 0;
while(x){
sum =sum+c[x];
x -= lowbit(x);
}
return sum;
}
//令A[i] += val
void add(int x, ll val){
while(x <= n){
c[x] =c[x]+val;
x += lowbit(x);
}
}
int main()
{
while(scanf("%lld%lld",&n,&m)!=-1)
{
m++;
for(int i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
b[i]=a[i];
}
sort(b+1,b+n+1);
int len=unique(b+1,b+n+1)-(b+1);
dp[0][0]=1;
for(int i=1;i<=m;i++)
{
memset(c,0,sizeof(c));
add(1,dp[i-1][0]); //val(a[o])=1
for(int j=1;j<=n;j++)
{
int pos=lower_bound(b+1,b+n+1,a[j])-b+1;
dp[i][j]=sum(pos-1);
add(pos,dp[i-1][j]);
}
}
ll ans = 0;
for (int i = 1; i <= n; i++)
ans = ans + dp[m][i];
printf("%lld\n", ans);
}
return 0;
}