NOIP5424. 【NOIP2017提高A组集训10.25】凤凰院凶真 LCIS 方案

来源:互联网 发布:java开发项目案例 编辑:程序博客网 时间:2024/06/06 00:46

题意:求lcis以及其方案。
原题:千帆渡
n<=5000.
很明显的DP。
设f[i][j]表示做到a的第i位,结尾是b的第j位,这样子便于记录方案。
那么明显有
f[i][j]=max(f[i][k-1])+1(b[j]>b[k]&&j>k)
由于规定了a[i]=b[j],所以上面的可以变成
f[i][j]=max(f[i][k-1])+1(a[i]>b[k]&&j>k)
至于j>k这个显然。
所以我们可以在dp过程中不断更新k,然后扫完b以后更新。
轻松切,然后至于方案的话记录一下每个状态由什么转移过来,然后由于我们的dp的状态定义是一定以j结尾的,所以这就很简单了。

#include<cstdio>#include<algorithm>#include<cstring>#define fo(i,a,b) for(int i=a;i<=b;i++)#define fd(i,a,b) for(int i=a;i>=b;i--)using namespace std;const int N=5e3+5;int a[N],b[N];int f[N][N],n,m,lis[N];struct node{    int x,y,z;}pre[N][N];int main(){    freopen("okarin.in","r",stdin);    freopen("okarin.out","w",stdout);    scanf("%d",&n);    fo(i,1,n)scanf("%d",&a[i]);    scanf("%d",&m);    fo(i,1,m)scanf("%d",&b[i]);    fo(i,1,n)    {        int k=0,x=0,y=0;        fo(j,1,m)        {            f[i][j]=f[i-1][j];            pre[i][j].z=f[i-1][j];            pre[i][j].x=i-1,pre[i][j].y=j;            if (a[i]>b[j]&&f[i-1][j]>k)            {                k=f[i-1][j];                x=i-1,y=j;            }            if (a[i]==b[j])            {                f[i][j]=k+1;                pre[i][j].z=k;                pre[i][j].x=x;                pre[i][j].y=y;            }        }    }    int ans=0,p=0;    fo(j,0,m)    if (ans<f[n][j])ans=f[n][j],p=j;    printf("%d\n",ans);    int minx=1e9,tot=0;    while(f[n][p])    {        if (f[n][p]<minx&&f[n][p]>0)        {            minx=f[n][p];            lis[++tot]=b[p];        }        int xx=pre[n][p].x;        int yy=pre[n][p].y;        n=xx,p=yy;    }    fd(i,tot,1)printf("%d ",lis[i]);    printf("\n");}
原创粉丝点击