最大连续和:
O(n) 算法: f[n] = max(f[n-1]+a[n], a[n])
O(nlogn) 算法:分治算法,算法竞赛入门经典有介绍
hackerrank给了一个 k-dane 算法:http://blog.csdn.net/joylnwang/article/details/6859677
最大子序列和(不要求连续):f[i]表示 1-i 最大子序列和,用d[i]表示最大子序列的结束位置。。
LIS问题:
nlogn算法: d[i] 保存长度为i的上升子序列的最后一个元素,维护d[i]使得d[i]总是最小。
可以这样理解,对于相同长度的IS,最后一个元素较小的子序列增长的“潜力”较大。
如果需要输出LIS,则 d[i] 保存的是下标,pa[i]保存上一个元素下标。代码见LCS问题。
// poj 2533
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<map>
#include<algorithm>
#include<vector>
#include<queue>
#include<cstring>
#include<set>
#include<list>
using namespace std;
const int maxn = 1000000;
const int inf = 0x7fffffff;
int T, n;
int a[maxn+5];
int d[maxn+5];
int main() {
#if 0
freopen("input.in", "r", stdin);
#endif
scanf("%d",&n);
if (n == 0) {printf("0");return 0;}
for (int i=1;i<=n;++i) scanf("%d", &a[i]);
for (int i=1;i<=n;++i) d[i] = inf;
d[0] = 0;
d[1] = a[1];
for (int i=2;i<=n;++i) {
int *p = lower_bound(d+1, d+n, a[i]);
if (*p > a[i])
*p = a[i];
}
int ans = 1;
for (int i=n;i>=1;--i)
if (d[i] != inf) {
ans = i;
break;
}
//for (int i=1;i<=n;++i) cout << d[i] << ' ';cout << endl;
printf("%d\n", ans);
return 0;
}
LCS问题:
nlogn算法:http://blog.csdn.net/non_cease/article/details/6918848
将LCS转换成LIS来解决,思想也非常容易理解。
#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
#include <map>
using namespace std;
#define rep(i, s, t) for(int (i)=(s);(i)<=(t);++(i))
#define urep(i, s, t) for(int (i)=(s);(i)>=(t);--(i))
const int inf = 0x7fffffff;
const int maxn = (int)(1e5);
int n, m, len;
int a[maxn+5];
int b[maxn+5];
int d[maxn+5];
int pa[maxn+5];
vector<int> sav[maxn+5];
vector<int> arr; // array to get LIS
map<int, int> ha;
bool cmp(int lhs, int rhs) {
if (lhs == inf) return false;
if (rhs == inf) return true;
return arr[lhs] < arr[rhs];
}
int main() {
#if 1
freopen("input.in", "r", stdin);
#endif
cin >> n >> m;
rep(i, 0, n-1) cin >> a[i];
rep(i, 0, m-1) cin >> b[i];
// map element in a [1-1e9] to [1-1e6], hash_value = position where the element firstly appearanced
// hash_value = ha[origin_value], origin_value = a[hash_value]
rep(i, 0, n-1) {
if (ha.count(a[i]) == 0) {
ha[a[i]] = i;
}
}
// for every distinct element in a, find its appearance in b
urep(i, m-1, 0) {
if (ha.count(b[i])) {
sav[ha[b[i]]].push_back(i);
}
}
rep(i, 0, n-1) {
if (ha.count(a[i])) {
int id = ha[a[i]];
int sz = sav[id].size();
rep(j, 0, sz-1) arr.push_back(sav[id][j]);
}
}
len = min(n, m);
rep(i, 0, len) d[i] = inf;
d[1] = 0;
d[0] = -1;
pa[0] = -1;
int sz = arr.size();
rep(k, 0, sz-2) cout << arr[k] << " ";cout << arr[sz-1] << endl;
rep(k, 1, sz-1) {
int *p = lower_bound(d+1, d+len, k, cmp);
if (cmp(k, *p)) {
pa[k] = *(p-1);
*p = k;
}
}
int idx;
for(idx=len;idx>=1;--idx)
if (d[idx] != inf) break;
vector<int> ans;
int cur = d[idx];
//cout << "length: " << idx << endl;
while (cur != -1) {
ans.push_back(b[arr[cur]]);
cur = pa[cur];
}
sz = ans.size();
rep(i, 0, sz-2) cout << ans[sz-1-i] << " ";cout << ans[0] << endl;
return 0;
}