题意:
给你一个长度为10W的数组,每个数范围0-100W
其中的0可以变为INT范围内的任意值
问最长上升子序列的长度
思路:
这题当时水过了。。数据太水
比赛结束了看了题解,简直膜拜神思路。。
0可以转化成任意整数,包括负数,
显然求LIS时尽量把0都放进去必定是正确的。
因此我们可以把0拿出来,对剩下的做O(nlogn)的LIS,
统计结果 的时候再算上0的数量。为了保证严格递增,
我们可以将每个权值S[i]减去i前面0的个数,
再做LIS,就能保证结果是严格递增的。
照着这题解写了一发AC了
/* *********************************************** Author :devil ************************************************ */ #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <vector> #include <queue> #include <set> #include <map> #include <string> #include <cmath> #include <stdlib.h> using namespace std; typedef long long LL; const int inf=0x3f3f3f3f; const int mod=1e9+7; const int N=1e5+10; int a[N],ans[N]; int main() { //freopen("in.txt","r",stdin); int t,m,x; scanf("%d",&t); for(int cas=1;cas<=t;cas++) { scanf("%d",&m); int cnt=0,n=0; for(int i=1;i<=m;i++) { scanf("%d",&x); if(!x) cnt++; else a[++n]=x-cnt; } if(!n) { printf("Case #%d: %d ",cas,m); continue; } ans[1]=a[1]; int len=1; for(int i=2;i<=n;i++) { if(a[i]>ans[len]) ans[++len]=a[i]; else { int pos=lower_bound(ans+1,ans+len,a[i])-ans; ans[pos]=a[i]; } } printf("Case #%d: %d ",cas,len+cnt); } return 0; }