51nod1376 最长上升子序列的数量

机房的人问我树状数组怎么做这题......

树状数组维护$len, num$表示$LIS$的长度和数量即可

复杂度$O(n log n)$

注:$O(n log n)$二分+单调栈才是真神仙

具体看代码

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

extern inline char gc() {
    static char RR[23456], *S = RR + 23333, *T = RR + 23333;
    if(S == T) fread(RR, 1, 23333, stdin), S = RR;
    return *S ++;
}
inline int read() {
    int p = 0, w = 1; char c = gc();
    while(c > '9' || c < '0') { if(c == '-') w = -1; c = gc(); }
    while(c >= '0' && c <= '9') p = p * 10 + c - '0', c = gc();
    return p * w;
}

#define mod 1000000007
#define ri register int
#define sid 50050

int n, cnp, H[sid], a[sid];
struct aha {
    int len, num;
} t[sid], f[sid];

void upd(aha &x, aha y) {
    if(x.len > y.len) return;
    if(x.len < y.len) x = y;
    else x.num += y.num, x.num %= mod;
}

aha qry(int x) {
    aha ret = { 0, 1 };
    for(ri i = x; i; i -= i &(-i)) upd(ret, t[i]);
    return ret;
}

aha add(int x, aha v) {
    for(ri i = x; i <= cnp; i += i & (-i)) upd(t[i], v);
}

int main() {
    n = read();
    for(ri i = 1; i <= n; i ++) a[i] = H[i] = read();
    sort(H + 1, H + n + 1);
    cnp = unique(H + 1, H + n + 1) - H - 1;
    for(ri i = 1; i <= n; i ++) a[i] = lower_bound(H + 1, H + cnp + 1, a[i]) - H;
    for(ri i = 1; i <= n; i ++) {
        f[i] = qry(a[i] - 1); f[i].len ++;
        add(a[i], f[i]);
    }
    aha ans = { 0, 0 };
    for(ri i = 1; i <= n; i ++) upd(ans, f[i]);
    printf("%d
", ans.num);
    return 0;
}
原文地址:https://www.cnblogs.com/reverymoon/p/9496040.html