【Codeforces 597C】 Subsequences - DP 主席树

来源:互联网 发布:java代码阅读器 app 编辑:程序博客网 时间:2024/05/16 18:20

  题意:给一个长度为n的排列,求长度为k+1的上升子序列个数。

  很显然的DP,f[j][i]表示到了第i位,取了长度为j的序列。
  f[j][i]=a[k]<=a[i]f[j1][k],边界为f[0][k]=1
  用个主席树随便滚动地维护一下前缀和就好。
  关于上升子序列系列的问题似乎都是可以这么乱搞的。
  时间复杂度O(Knlogn)
  注意是长度为k+1……是上升子序列……
  

#include <bits/stdc++.h>using namespace std;#define rep(i,a,b) for(int i = a , _ = b ; i <= _ ; i ++)#define per(i,a,b) for(int i = a , _ = b ; i >= _ ; i --)#define cr(x) memset(x , 0 , sizeof x)#define maxn 100007#define maxs 2000007inline int rd() {    char c = getchar();    while (!isdigit(c)) c = getchar() ; int x = c - '0';    while (isdigit(c = getchar())) x = x * 10 + c - '0';    return x;}typedef long long ll;typedef int seg_int[maxs];typedef ll  seg_ll [maxs];typedef int arr[maxn];int n , m;struct CMT {    arr rt;    seg_int lc , rc;    seg_ll val ;    int tot , p;    ll v;    void update(int pr , int&nr , int l , int r) {        if (!nr) nr = ++ tot ;        val[nr] = val[pr] + v;        if (l == r) return;        int m = l + r >> 1;        if (p <= m)            rc[nr] = rc[pr] , update(lc[pr] , lc[nr] , l , m);        else            lc[nr] = lc[pr] , update(rc[pr] , rc[nr] , m + 1 , r);    }    ll query(int&nr , int l , int r) {        if (!nr) return 0;        if (r <= p) return val[nr];        int m = l + r >> 1;        if (p <= m) return query(lc[nr] , l , m);        else return val[lc[nr]] + query(rc[nr] , m + 1 , r);    }    inline void M(int pr , int nr , int _p , ll _v) {        p = _p , v = _v;        update(rt[pr] , rt[nr] , 1 , n);    }    inline ll Q(int nr , int _p) {        p = _p;        return query(rt[nr] , 1 , n);    }    inline void C() {        tot = 0;        cr(rt) , cr(lc) , cr(rc) , cr(val);    }}tr[2];arr a;void input() {    n = rd() , m = rd() + 1;    rep (i , 1 , n) a[i] = rd();    std::reverse(a + 1 , a + n + 1);}void solve() {    int cur = 0 , pre = 1;    per (i , n , 1) tr[cur].M(i + 1 , i , a[i] , 1);    rep (j , 2 , m) {        cur ^= 1 , pre ^= 1;        tr[cur].C();        per (i , n , 1)            tr[cur].M(i + 1 , i , a[i] , tr[pre].Q(i + 1 , a[i]));    }    using namespace std;    cout << tr[cur].Q(1 , n + 1) << endl;}int main() {    #ifndef ONLINE_JUDGE        freopen("data.txt" , "r" , stdin);    #endif    input();    solve();    return 0;}
0 0