【Codeforces 597C】【DP 树状数组优化】Subsequences 【n个不同数,长度为k+1的LIS数】

传送门:C. Subsequences

描述:

C. Subsequences
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

For the given sequence with n different elements find the number of increasing subsequences with k + 1 elements. It is guaranteed that the answer is not greater than 8·1018.

Input

First line contain two integer values n and k (1 ≤ n ≤ 105, 0 ≤ k ≤ 10) — the length of sequence and the number of elements in increasing subsequences.

Next n lines contains one integer ai (1 ≤ ai ≤ n) each — elements of sequence. All values ai are different.

Output

Print one integer — the answer to the problem.

Examples
input
5 2
1
2
3
5
4
output
7

题意:

给你n(1e5)个数a[],每个数都在[1,n]范围且数值各不相同。
我们想要求,长度为k+1(0<=k<=10)的LIS的数量是多少个

思路:

用dp[i][j]表示最后一个数的位置为i,长度为j的LIS数。
具体的转移方程则是f[i][j]=∑f[p][j-1],p<i且a[p]<a[i]。
然而这个DP方程却是O(n*n*k)的。
于是,我们要采取优化策略。我们需要找到在它之间比它小的数。
在它之间,可以通过扫描顺序解决。
而比它小,则可以通过树状数组动态更新和解决。

代码:

#include <bits/stdc++.h>
#define pr(x) cout << #x << "= " << x << "  " ;
#define pl(x) cout << #x << "= " << x << endl;
#define ll __int64
using  namespace  std;

template<class T> void read(T&num) {
    char CH; bool F=false;
    for(CH=getchar();CH<'0'||CH>'9';F= CH=='-',CH=getchar());
    for(num=0;CH>='0'&&CH<='9';num=num*10+CH-'0',CH=getchar());
    F && (num=-num);
}
const int N=1e5+10;

int n,k;
ll dp[N][15];

void update(int i,int j,ll x){
  while(i<=n){
    dp[i][j]+=x;
    i+=i&-i;
  }
}

ll query(int i,int j){
  ll s=0;
  while(i>0){
    s+=dp[i][j];
    i-=i&-i;
  }
  return s;
}

int  main(){
  #ifndef ONLINE_JUDGE
  freopen("in.txt","r",stdin);
  #endif

  read(n);read(k);
  update(1, 0, 1);
  for(int i=1; i<=n; i++){
    int x;read(x);
    for(int j=k+1; j>=1; j--)update(x, j, query(x, j-1));//逆推
  }
  printf("%lld\n",query(n, k+1)); 
  return 0;
}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值