3 1 2 3 2 2 1
1 3
线段树+dp,dp[i]表示以第i个元素结尾的LIS的长度,线段树维护此LIS的最靠右的起始位置和长度,靠右是是为了完全统计出这样的区间,最后只要O(n)的时间去统计
#include <cstdio> #include <cstring> #include <cstdlib> #include <iostream> #include <algorithm> using namespace std; const int N = 100010; const int inf = -0x3f3f3f3f; int xis[N]; int arr[N]; int dp[N]; int sta[N]; int end[N]; int ans, s; int cnt; struct node { int l, r; int val, s; }tree[N << 2]; void build(int p, int l, int r) { tree[p].l = l; tree[p].r = r; tree[p].val = inf; tree[p].s = inf; if (l == r) { return; } int mid = (l + r) >>1; build(p << 1, l, mid); build(p << 1 | 1, mid + 1, r); } int BinSearch(int val) { int l = 1, r = cnt, mid; int ans; while (l <= r) { mid = (l + r) >> 1; if (xis[mid] > val) { r = mid - 1; } else if (xis[mid] < val) { l = mid + 1; } else { ans = mid; break; } } return ans; } void update(int p, int pos, int val, int s) { if (tree[p].l == tree[p].r) { if (tree[p].val == val && tree[p].s < s) { tree[p].s = s; } else if (tree[p].val < val) { tree[p].val = val; tree[p].s = s; } return; } int mid = (tree[p].l + tree[p].r) >> 1; if (pos <= mid) { update(p << 1, pos, val, s); } else { update(p << 1 | 1, pos, val, s); } if (tree[p << 1].val > tree[p << 1 | 1].val) { tree[p].val = tree[p << 1].val; tree[p].s = tree[p << 1].s; } else if (tree[p << 1].val < tree[p << 1 | 1].val) { tree[p].val = tree[p << 1 | 1].val; tree[p].s = tree[p << 1 | 1].s; } else { tree[p].s = max(tree[p << 1].s, tree[p << 1 | 1].s); } } void query(int p, int l, int r) { if (tree[p].l >= l && tree[p].r <= r) { if (tree[p].val > ans) { ans = tree[p].val; s = tree[p].s; } else if (tree[p].val == ans && s < tree[p].s) { s = tree[p].s; } return; } int mid = (tree[p].l + tree[p].r) >> 1; if (r <= mid) { query(p << 1, l, r); } else if (l > mid) { query(p << 1 | 1, l, r); } else { query(p << 1, l, mid); query(p << 1 | 1, mid + 1, r); } } int main() { int n; while (~scanf("%d", &n)) { __int64 ret = 0; cnt = 0; int tmp = 0; for (int i = 1; i <= n; ++i) { scanf("%d", &arr[i]); xis[++cnt] = arr[i]; } if (n == 1) { printf("1\n"); continue; } sort (xis + 1, xis + cnt + 1); cnt = unique(xis + 1, xis + cnt + 1) - xis - 1; dp[1] = 1; sta[1] = 1; build(1, 1, cnt); update(1, BinSearch(arr[1]), dp[1], sta[1]); for (int i = 2; i <= n; ++i) { ans = inf; s = inf; if (BinSearch(arr[i]) == 1) { dp[i] = 1; sta[i] = i; } else { query(1, 1, BinSearch(arr[i]) - 1); } if (ans == inf) { dp[i] = 1; sta[i] = i; } else { dp[i] = ans + 1; sta[i] = s; } update(1, BinSearch(arr[i]), dp[i], sta[i]); tmp = max(tmp, dp[i]); } int last = n + 1; for (int i = n; i >= 1; --i) { if (dp[i] == tmp) { end[i] = last - 1; last = i; } } for (int i = 1; i <= n; ++i) { if (dp[i] == tmp) { ret += (__int64)sta[i] * (__int64)(end[i] - i + 1); } } printf("%I64d\n", ret); } return 0; }
原文地址:http://blog.csdn.net/guard_mine/article/details/41786567