https://yukicoder.me/problems/no/992
前提知識
解説
https://yukicoder.me/submissions/430662
Aに負の数が入っているのは、ちょっと面倒な気がする。
かつ、配列Aは実際の値は特に重要ではなく、数の大小だけが問題なので、座標圧縮して、[0,N)におさめておこう。
LISの解法の、セグメントツリー解法をベースに考えていこう。
先頭から順番に数を見ていきながら、セグメントツリーを更新していく。
具体的には、以下のようにセグメントツリーを作成する。
i番目の要素は、今まで見てきた要素の最後がi=A[j]であるLISの(最長の長さ, その組み合わせ)
これを特殊なマージをしていく。
最長の長さ同士のマージであれば、組み合わせを足してマージする。
そうでないなら、長さが異なるなら、長いほうを利用する。
単位元は(0,1)とすればよい。
これで、更新していき、最終的に全体をgetして、組み合わせ部分を答えると答え。
単位元のマージの仕方と、自身を更新するときにしっかりマージするのに注意。
int N, A[201010]; SegTree<1 << 18> st; //--------------------------------------------------------------------------------------------------- void _main() { cin >> N; rep(i, 0, N) cin >> A[i]; compress1(A, N); rep(i, 0, N) { auto p = st.get(0, A[i]); p.first++; auto cu = st[A[i]]; st.update(A[i], st.comp(cu, p)); } cout << st.get(0, N).second << endl; }