51nod 1218 最长递增子序列 V2 【最长递增+复杂判断】

来源:互联网 发布:吃饭 叫号软件 编辑:程序博客网 时间:2024/06/15 14:55

1218 最长递增子序列 V2 【最长递增+复杂判断】  

1218 最长递增子序列 V2
基准时间限制:1 秒 空间限制:131072 KB 分值: 160 难度:6级算法题
 收藏
 关注
数组A包含N个整数。设S为A的子序列且S中的元素是递增的,则S为A的递增子序列。如果S的长度是所有递增子序列中最长的,则称S为A的最长递增子序列(LIS)。A的LIS可能有很多个。例如A为:1 3 2 0 4,1 3 4,1 2 4均为A的LIS。其中元素1和4一定会出现在LIS当中,元素2和3可能会出现在LIS当中,元素0一定不会出现在LIS当中。给出数组A,输出哪些数可能出现在LIS中,哪些数一定出现在LIS中。输出数字对应的下标,下标编号从1开始,编号为1 - N。例如:1 3 2 0 4,可能出现的元素为3和2,对应的下标为2和3。一定出现的元素为1和4,对应下标为1和5.
Input
第1行:1个数N,表示数组的长度。(1 <= N <= 50000)第2 - N + 1行:每行1个数A[i],表示数组的元素(0 <= A[i] <= 10^9)
Output
第1行:可能出现在LIS中的数的下标,中间用空格分隔。(输出的下标按照递增排序)第2行:一定会出现在LIS中的数的下标,中间用空格分隔。(输出的下标按照递增排序)
Input示例
513204
Output示例
A:2 3B:1 5



变量比较多  不过代码很短  不难理解


#include <stdio.h>#include <bits/stdc++.h>using namespace std;typedef long long ll;int s[50005],dex[50005],maxn[50005],cnt[50005],m[50005],vis[50005];int n,len=1;   //s保存输入数据  dex保存最长递增子序列 maxn保存当前数是第几大 int main()     //cnt表示第x大的数出现的次数 vis表示这个数被使用过 m表示从后遍历第k大的数的最大值 {cin>>n;cin>>s[0];dex[0]=s[0];maxn[0]=1;for(int i=1;i<n;i++){cin>>s[i];int k=lower_bound(dex,dex+len,s[i])-dex;maxn[i]=k+1;if(k==len){dex[len++]=s[i];}else{dex[k]=s[i];}}m[len+1]=1<<30;for(int i=n-1;i>=0;i--){if(m[maxn[i]+1]>s[i]){vis[i]=maxn[i];cnt[maxn[i]]++;m[maxn[i]]=max(m[maxn[i]],s[i]);}}cout<<"A:";for(int i=0;i<n;i++){if(vis[i] && cnt[vis[i]]>1) printf("%d ",i+1);}cout<<endl<<"B:";for(int i=0;i<n;i++){if(vis[i] && cnt[vis[i]]==1)printf("%d ",i+1);}return 0;}



0 0
原创粉丝点击