标签:long int len re Zero 热身 purpose 序列 define
简要题意:
长度为n的数组,每个数字为S[i],$0$是一种很神奇的数字,你想要的,它都可以变!
问这个序列的最长上升子序列长度为多少?
分析:
我们将除了‘0’以外的S[i],减去i之前出现的‘0’的个数,最后求得排除‘0’后的最长上升子序列长度,加上‘0’的个数,就是我们要求的答案。
在这里我不主要分析该做法的正确性,我们引入一个O(nlogn)的方法来求最长上升子序列。
LIS (点此看题)
贪心+二分
我们令f[i]表示长度为i的上升子序列,末尾的最小值。
这里我们因为贪心,所以子序列末尾越小越好。
我们按顺序枚举给出的数组S[i],然后对f[]二分查找除小于S[i]的最大的f[j],并用它将f[j+1]更新。
#include<bits/stdc++.h> using namespace std; #define re register int #define LL long long const int N=1e5+5; int n, a[N], b[N], len; signed main() { scanf("%d",&n); for(re i=1;i<=n;++i) scanf("%d",&a[i]); for(re i=1;i<=n;++i) { if(a[i] > b[len]) b[++len] = a[i]; else { int tp = lower_bound(b+1, b+1+len, a[i])-b; b[tp] = a[i]; } } printf("%d", len); }
上马
#include<bits/stdc++.h> using namespace std; #define re register int #define LL long long const int N=1e5+5; int n, a[N], b[N], num, len; inline void work() { num = len = 0; scanf("%d",&n); for(re i=1;i<=n;++i) { scanf("%d",&a[i]); if(a[i] == 0) { num ++; a[i] = 1e9; } else { a[i] -= num; } } b[0] = -1e9; for(re i=1;i<=n;++i) { if(a[i] == 1e9) continue; if(a[i] > b[len]) b[++len] = a[i]; else { int tp = lower_bound(b+1, b+1+len, a[i])-b; b[tp] = a[i]; } } printf("%d\n", len+num); } signed main() { int T; scanf("%d",&T); for(re i=1;i<=T;++i) { printf("Case #%d: ",i); work(); } return 0; }View Code
标签:long,int,len,re,Zero,热身,purpose,序列,define 来源: https://www.cnblogs.com/kzsn/p/15040974.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。