[TJOI2014]上升子序列
阿新 • • 發佈:2018-09-13
c++ sum class n) script 去重 %d lower www.
Description
BZOJ5157
Luogu3970
求原序列有多少個上升子序列。
Solution
本來想先暴力DP一下拿個部分分,但是由於不會去重,這個思路就破滅了。
後來手玩的時候突然發現,不就是把比這個數小的答案都加起來就是它的答案了啊,形式化的說就是\(f_i=\sum a_j (j < i,a_j<a_i)\)。
這樣的話離散化一下樹狀數組求前綴和就可以水過了...
Code
#include <cstdio> #include <algorithm> const int N = 1e5 + 10; const int MOD = 1e9 + 7; int f[N], a[N], b[N], n, c[N]; void add(int p, int x) { while (p <= n) { f[p] = (f[p] + x) % MOD; p += p&-p; } } int query(int p) { int ans = 0; while (p > 0) { ans = (ans + f[p]) % MOD; p -= p&-p; } return ans; } int main() { scanf("%d", &n); for (int i = 1; i <= n; ++i) { scanf("%d", &a[i]); c[i] = a[i]; } std::sort(c+1, c+n+1); int now = std::unique(c+1, c+n+1) - c; for (int i = 1; i <= n; ++i) { b[i] = std::lower_bound(c+1, c+now, a[i]) - c; } for (int i = 1; i <= n; ++i) { int ans = query(b[i]-1)+1; add(b[i], (query(b[i])-query(b[i]-1)+MOD)%MOD*-1); add(b[i], ans); } int ans = (query(n) - now + 1 + MOD) % MOD; printf("%d\n", ans); return 0; }
[TJOI2014]上升子序列