Codeforces 977F - Consecutive Subsequence - [map优化DP]
题目链接:http://codeforces.com/problemset/problem/977/F
题意:
给定一个长度为 n 的整数序列 a[1∼n],要求你找到一个它最长的一个子序列,该子序列满足单调连续递增。
子序列可以不连续,单调连续递增即例如 [4,5,6,7] 或者 [6,7,8,9,10] 这样的。
题解:
f[i] 表示以 a[i] 为结尾的最长连续递增子序列,那么要转移就需要找到 [1,i−1] 这个区间内,某个满足 a[j]=a[i]−1 的最大的 f[j],转移得到 f[i]=f[j]+1。
这样一来,暴力地找的话时间复杂度是 O(n2),用map优化一下,mp[x] 维护所有 a[i]=x 的 f[i] 的最大值,同时存下这个位置 i,即可做到 O(nlogn) 的转移,并且还可以逆向的找到转移到答案的整个过程。
AC代码:
#include<bits/stdc++.h> using namespace std; typedef pair<int,int> P; #define mk(x,y) make_pair(x,y) #define fi first #define se second const int maxn=2e5+10; int n,a[maxn]; int f[maxn],pre[maxn]; map<int,P> mp; int main() { scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); for(int i=1;i<=n;i++) { int x=a[i]-1; if(!mp.count(x)) f[i]=1, pre[i]=0; else f[i]=mp[x].fi+1, pre[i]=mp[x].se; if(mp[a[i]].fi<f[i]) mp[a[i]]=mk(f[i],i); } int idx=1; for(int i=1;i<=n;i++) if(f[i]>f[idx]) idx=i; printf("%d\n",f[idx]); vector<int> ans; while(idx) ans.push_back(idx), idx=pre[idx]; for(int i=ans.size()-1;i>=0;i--) printf("%d ",ans[i]); }
转载请注明出处:https://dilthey.cnblogs.com/
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步