樹狀陣列+離散化
阿新 • • 發佈:2021-10-11
給定一個長度為nn的整數序列a1,a2,…,ana1,a2,…,an。
請你選出一個該序列的嚴格上升子序列,要求所選子序列的各元素之和儘可能大。
請問這個最大值是多少?
輸入格式
第一行包含整數nn。
第二行包含nn個整數a1,a2,…,ana1,a2,…,an。
輸出格式
輸出最大的上升子序列和。
資料範圍
對於前三個測試點,1≤n≤41≤n≤4。
對於全部測試點,1≤n≤105,1≤ai≤1091≤n≤105,1≤ai≤109。
輸入樣例1:
2
100 40
輸出樣例1:
100
輸入樣例2:
4
1 9 7 10
輸出樣例2:
20
樣例解釋
對於樣例11,我們只選取100100。
對於樣例22,我們選取1,9,10 1,9,10。
#include <algorithm> #include <cstring> #include <iostream> #include <unordered_map> using namespace std; const int N = 1e5 + 10; typedef long long LL; LL n, a[N], b[N], sum[N], maxSum[N]; unordered_map<int, LL> mp; LL c[N]; // 查詢字首和:查詢序列 a 第 1~x 個數的和 //找出在x之前的元素的最大值LL ask(LL x) { LL ans = 0; for (; x; x -= x & -x) ans = max(ans, c[x]); return ans; } // 單點增加:給序列中的一個數 a[x] 加上 y // 演算法:自下而上每個節點都要增加 y void add(int x, LL y) { for (; x <= n; x += x & -x) c[x] = max(c[x], y); } int main() { cin >> n; for (int i = 1; i <= n; i++) cin >> a[i]; memcpy(b, a,sizeof a); sort(b + 1, b + n + 1); LL m = 0; for (int i = 1; i <= n; i++) { if (!mp.count(b[i])) mp[b[i]] = ++m; } //相當於離散化 for (int i = 1; i <= n; i++) { sum[i] = ask(mp[a[i]] - 1) + a[i]; add(mp[a[i]], sum[i]); } LL ans = 0; for (int i = 1; i <= n; i++) { ans = max(ans, sum[i]); } cout << ans << endl; return 0; }