[51Nod] 1218 最长递增子序列 V2
如何判断一个元素是否一定在LIS中?设f[i]为以ai结尾的LIS长度,g[i]为以ai开头的LIS长度,若f[i]+g[i]-1==总LIS,那么i就一定在LIS中出现
显然只出现一次的元素一定是必选,剩下的就是可选了。
#include<algorithm> #include<iostream> #include<cstring> #include<cstdio> #include<vector> using namespace std; const int MAXN=500005; vector<int> vec[MAXN],A,B; int tmp[MAXN],mx[MAXN]; int a[MAXN],f[MAXN],g[MAXN],n; int b[MAXN]; int t[MAXN],t2[MAXN]; inline void upmax(int &x,int y){x=max(x,y);} void update(int x,int w){for(int i=x;i<=n;i+=i&-i)upmax(t[i],w);} int query(int x){int _=0;for(int i=x;i;i-=i&-i)upmax(_,t[i]);return _;} void update2(int x,int w){for(int i=n-x+1;i<=n;i+=i&-i)upmax(t2[i],w);} int query2(int x){int _=0;for(int i=n-x+1;i;i-=i&-i)upmax(_,t2[i]);return _;} int main(){ n=rd(); for(int i=1;i<=n;i++)tmp[i]=a[i]=rd(); sort(tmp+1,tmp+1+n); int tot=unique(tmp+1,tmp+1+n)-1-tmp; for(int i=1;i<=n;i++)a[i]=lower_bound(tmp+1,tmp+1+tot,a[i])-tmp; int mxf=0; for(int i=1;i<=n;i++){ f[i]=query(a[i]-1)+1; update(a[i],f[i]); upmax(mxf,f[i]); } for(int i=n;i>=1;i--){ g[i]=query2(a[i]+1)+1; update2(a[i],g[i]); } for(int i=1;i<=n;i++){ if(f[i]+g[i]!=mxf+1)continue; vec[f[i]].push_back(i); } for(int i=1;i<=n;i++){ int s=vec[i].size(); if(s==0)continue; if(s==1){A.push_back(vec[i][0]);continue;} for(int j=0;j<s;j++)B.push_back(vec[i][j]); } sort(A.begin(),A.end()); sort(B.begin(),B.end()); vector<int>::iterator it; printf("A:"); for(it=B.begin();it!=B.end();it++)printf("%d ",*it); putchar('\n'); printf("B:"); for(it=A.begin();it!=A.end();it++)printf("%d ",*it); }
本文来自博客园,作者:GhostCai,转载请注明原文链接:https://www.cnblogs.com/ghostcai/p/9643278.html