傳送門
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 函式得到所有數都插入完後的序列,然後...