P3970 TJOI2014 上公升子串行

2022-05-20 02:30:32 字數 1124 閱讀 7836

傳送門

dp十分顯然的dp,但是不好寫

設 f[ i ] 表示以第 i 個數作結尾時的方案數,原序列為 a

如果不考慮相同的序列:

那麼轉移就是 σ f[ j ] (0< j < i && a [ j ] < a [ i ])

複雜度為 o(n^2)

考慮優化:

先去重 ,得到陣列 b

每次把f [ i ] 加到樹狀陣列裡a [ i ]的值 在 b 中的位置的位置

那麼 f [ i ] 就等於 query(a [ i ] 的值在 b 中的位置-1) (query為樹狀陣列的詢問操作)

(上兩行很重要,自己在腦子裡想象一下,一定要理解原因)

然後考慮去掉相同的序列

很簡單只要每次更新完 f [ i ] 時把 f [ i ] 減去前面 a 中所有值為 a[ i ] 的位置(設為 j)

的 f[ j ]的和(還是要在腦子裡想象一下...或者看**來理解...

最後注意要減去長度為 1 的方案數以及一些細節

**其實不長

#include#include

#include

#include

#include

using

namespace

std;

const

int n=1e5+7

;const

int mo=1e9+7

;int

n,a[n],f[n],b[n],t[n],las[n],m,ans;

//t是樹狀陣列的陣列,las[i]是前面a中所有值為a[i]的位置(設為j)的f[j]的和

inline int query(int

x)

return

res;

}inline

void add(int x,intv)}

intmain()

ans-=m; if(ans<0) ans+=mo;//

減去長度為1的方案數

cout

}

TJOI2014 上公升子串行

bzoj5157 luogu3970 求原序列有多少個上公升子串行。本來想先暴力dp一下拿個部分分,但是由於不會去重,這個思路就破滅了。後來手玩的時候突然發現,不就是把比這個數小的答案都加起來就是它的答案了啊,形式化的說就是 f i sum f j j i,a j。這樣的話離散化一下樹狀陣列求字首和...

TJOI2014 上公升子串行

bzoj5157 luogu3970 求原序列有多少個上公升子串行。本來想先暴力dp一下拿個部分分,但是由於不會去重,這個思路就破滅了。後來手玩的時候突然發現,不就是把比這個數小的答案都加起來就是它的答案了啊,形式化的說就是 f i sum f j j i,a j。這樣的話離散化一下樹狀陣列求字首和...

P4309 TJOI2013 最長上公升子串行

給定乙個序列,初始為空。現在我們將1到n的數字插入到序列中,每次將乙個數字插入到乙個特定的位置。每插入乙個數字,我們都想知道此時最長上公升子串行長度是多少?因為每次插入的數是按順序從小到大的,所以我們可以從後往前計算 我們先用 vector 自帶的 insert 函式得到所有數都插入完後的序列,然後...