最长递增子序列
编程之美2.16节。较容易想到的方法是O(n^2)的。这里有一个细节没有使用到,假设记录下所有长度的子序列结果,那么我们可以保证长度为n的子序列尾元素一定大于等于长度为n-1的子序列尾元素,否则的话,我们可以从长度为n的子序列中获取一个n-1的子序列,将之前的结果覆盖。利用这个性质,我们可以获得一个O(nlogn)的算法:
template<class It>
vector<typename iterator_traits<It>::value_type>
lis(It first, It last) {
typedef iterator_traits<It>::value_type value_type;
vector<value_type> ends;
vector< vector<value_type> > seqs;
for (It it = first; it != last; ++it) {
vector<value_type>::iterator pit = lower_bound(ends.begin(), ends.end(), *it);
if (pit == ends.end()) {
ends.push_back(*it);
seqs.push_back(seqs.size()? seqs.back(): vector<value_type>());
seqs.back().push_back(*it);
}
else {
*pit = *it;
size_t d = distance(ends.begin(), pit);
seqs[d] = d? seqs[d-1]: vector<value_type>();
seqs[d].push_back(*it);
}
}
return seqs.back();
}
int main() {
int n;
while (cin>>n) {
if (!n) break;
vector<int> in;
while (n--) *back_inserter(in) = *istream_iterator<int>(cin);
vector<int> seq = lis(in.begin(), in.end());
for (size_t i = 0; i < seq.size(); ++i) {
if (i) cout<<' ';
cout<<seq[i];
}
cout<<'\n';
}
return 0;
}