1. 程式人生 > 其它 >樹狀陣列+離散化

樹狀陣列+離散化

給定一個長度為nn的整數序列a1,a2,,ana1,a2,…,an。

請你選出一個該序列的嚴格上升子序列,要求所選子序列的各元素之和儘可能大。

請問這個最大值是多少?

輸入格式

第一行包含整數nn。

第二行包含nn個整數a1,a2,,ana1,a2,…,an。

輸出格式

輸出最大的上升子序列和。

資料範圍

對於前三個測試點,1n41≤n≤4。
對於全部測試點,1n105,1ai1091≤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; }