给一个数列 其中0可以替换成任意interger(包括负数), 在此基础上求最长递增子序列
摘自 http://blog.csdn.net/l954688947/article/details/52057455 解题思路:无疑LIS,将所有的0全部提取出来, 求出此时序列的LIS(不含0的),这是针对0在子序列的外面的情况, 如0,1,2,3,0.那么如果0在子序列中间怎么办? 很简单,把读入的非0的数的值减去这个数前面0的个数即可, 如1,2,0,3,4。在提取出0后序列其实为1,2,2,3, LIS的长度为3,加上0的个数则为答案。 好像有点道理。。。。
#include <iostream> #include <algorithm> #include <cstdio> #include <cstring> #include <queue> #include <vector> #include <cmath> #include <stack> #include <string> #include <map> #include <set> #define pi acos(-1) #define LL long long #define ULL unsigned long long #define inf 0x3f3f3f3f #define INF 1e18 #define lson l,mid,rt<<1 #define rson mid+1,r,rt<<1|1 using namespace std; typedef pair<int, int> P; const int maxn = 1e5 + 5; int a[maxn]; int seq[maxn], len[maxn]; int main(void) { // freopen("C:\\Users\\wave\\Desktop\\NULL.exe\\NULL\\in.txt","r", stdin); int T, cas = 1, n, i, j, cnt, t, k, lmax; scanf("%d", &T); while (T--) { scanf("%d", &n); t = cnt = 0; for (i = 1; i <= n; i++){ scanf("%d", &k); if (!k) cnt++; else a[++t] = k - cnt; } if (!t){ printf("Case #%d: %d\n", cas++, n); continue; } seq[1] = a[1]; len[1] = 1; lmax = 1; for (i = 2; i <= t; i++){ if (a[i] > seq[lmax]) seq[++lmax] = a[i]; else { int pos = lower_bound(seq+1, seq+lmax, a[i]) - seq; seq[pos] = a[i]; } } printf("Case #%d: %d\n", cas++, lmax+cnt); } return 0; }