「 HDOJ P2227 」 Find the nondecreasing subsequences

# 題目大意

就是找不降低子序列的個數。ios

 

# 解題思路

一開始想着先離散化,而後再作個 $dp$,發現用 $dp$ 的話時間複雜度是 $\text{O}(n^2)$ 的,穩穩超時。數組

這裏說說 $dp$:spa

設 $dp[i]$ 表示以 $a[i]$ 爲結尾的不降低子序列的個數。code

那麼狀態轉移方程就顯而易見了:blog

$$dp[i] = sum(dp[j])+1,a[j]<=a[i]\&\&j<i$$string

遂放棄 $dp$,轉向另外一種思路:樹狀數組。it

由於要求逆序列的個數。因此選擇用樹狀數組來作,思路以下:io

將數據離散化後,按照原來輸入的順序從小到大將每個數的影響加到樹狀數組中。那麼影響是啥?class

就是會對當前這個數後面的比它大的數字形成影響,由於會構成逆序列。而後你就牛逼了。。。stream

這樣的話,每次詢問一個數時,只有它前面的數的影響才被加了進去。就能夠保證詢問的正確性。

 

# 附上代碼

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int maxn = 1e5+3, HA = 1e9+7;
int n, s[maxn], a[maxn], tmp[maxn], bit[maxn], NI[maxn];
inline int lowbit(int x) {return x & -x;}
inline void add(int pos, int num) {
    while (pos <= n) {
        bit[pos] = ((num % HA) + (bit[pos] % HA)) % HA;
        pos += lowbit(pos);
    }
}
inline int query(int pos) {
    int res = 0;
    while (pos >= 1) {
        res = ((bit[pos] % HA) + (res % HA)) % HA;
        pos -= lowbit(pos);
    }
    return res;
}
int main() {
    while (~scanf("%d", &n)) {
        memset(NI, 0, sizeof(NI));
        memset(bit, 0, sizeof(bit));
        for(int i=1; i<=n; i++) {
            scanf("%d", &s[i]);
            tmp[i] = s[i];
        }
        sort(tmp+1, tmp+1+n);
        for(int i=1; i<=n; i++)
            a[i] = lower_bound(tmp+1, tmp+1+n, s[i])-tmp;
        for(int i=1; i<=n; i++) {
            NI[i] = query(a[i]);
            NI[i] %= HA;
            add(a[i], NI[i] + 1);
        }
        printf("%d\n", query(n));
    }
}
相關文章
相關標籤/搜索