$ZOJ\ 2432\ Greatest\ Common\ Increasing\ Subsequence$

传送门

 

$Description$

求两个序列的最长公共上升子序列

 

$Solution$

$f[i][j]$表示$a$序列匹配到$i$和$b$序列匹配到$j$的最长上升序列的长度,这里并不要求$a[i]==b[j]$。

两层循环,外层$i=1...n1$,内层$j=1...n2$

转移:

$f[i][j]=max(f[i-1][1...j-1](if\  b[j]<a[i]))+1$

这里的$max(f[i-1][i...j-1](if\  b[j]<a[i]))$不用每次单独枚举,只要在循环内即使更新就可以了

 或者,也可以用树状数组来维护.

 

$Code$

 

#include<bits/stdc++.h>
#define Ri register int
#define il inline
#define go(i,a,b) for(Ri i=a;i<=b;++i)
#define yes(i,a,b) for(Ri i=a;i>=b;--i)
#define e(i,u) for(Ri i=b[u];i;i=a[i].nt)
#define ll long long
#define db double
using namespace std;
il int read()
{
    Ri x=0,y=1;char c=getchar();
    while(c<'0' || c>'9'){if(c=='-')y=-1;c=getchar();}
    while(c>='0' && c<='9'){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
    return x*y;
}
const int N=2010;
int n,m,a[N],b[N],f[N][N],as,d[N],t[N][N*4];
struct nd{int d,p;}c[N];
il bool cmp(nd x,nd y){return x.d<y.d;}
il int lowbit(Ri x){return x&(-x);}
il void change(Ri i,Ri j,Ri dat)
{
    while(i<=n)
    {
        t[j][i]=max(t[j][i],dat);
        i+=lowbit(i);
    }
}
il int sum(Ri i,Ri j)
{
    Ri ret=0;
    while(i>0)
    {
        ret=max(ret,t[j][i]);
        i-=lowbit(i);
    }
    return ret;
}
int main()
{
    freopen("lcis.in","r",stdin);
    freopen("lcis.out","w",stdout);
    n=read(),m=read();
    go(i,1,n)a[i]=read(),c[i]=(nd){a[i],i};
    go(i,1,m)b[i]=read();
    sort(c+1,c+n+1,cmp);
    go(i,1,n)
        if(i>=2 && c[i].d==c[i-1].d)d[c[i].p]=d[c[i-1].p];
        else d[c[i].p]=i;
    go(i,1,n)
    {
        go(j,1,m)
        { 
            f[i][j]=max(f[i][j],f[i][j-1]);
            if(a[i]==b[j])
                f[i][j]=max(f[i][j],sum(d[i]-1,j-1)+1);
        }
        go(j,1,m)change(d[i],j,f[i][j]);
    }
    go(i,1,n)as=max(as,f[i][m]);
    printf("%d\n",as);
    return 0;
}
View 树状数组 Code

 

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #define Rg register
 5 #define il inline
 6 #define db double
 7 #define ll long long
 8 #define mem(a,b) memset(a,b,sizeof(a));
 9 #define go(i,a,b) for(Rg int i=a;i<=b;i++)
10 #define yes(i,a,b) for(Rg int i=a;i>=b;i--)
11 using namespace std;
12 il int read()
13 {
14     int x=0,y=1;char c=getchar();
15     while(c<'0'||c>'9'){if(c=='-')y=-1;c=getchar();}
16     while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+c-'0';c=getchar();}
17     return x*y;
18 }
19 const int N=501;
20 int T,n1,n2,ans,a[N],b[N],al[N],f[N][N],lst[N][N];
21 il void sol()
22 {
23     ans=0;mem(f,0);int x=n1,y=0,t;
24     go(i,1,n1)
25     {
26         t=0;
27         go(j,1,n2)
28         {
29             if(a[i]!=b[j])f[i][j]=f[i-1][j];
30             if(a[i]>b[j]&&f[i][j]>f[i][t])t=j;
31             if(a[i]==b[j])f[i][j]=f[i][t]+1,lst[i][j]=t;
32             //cout<<"f["<<i<<"]["<<j<<"]:"<<f[i][j]<<endl;
33         }
34     }
35     go(i,1,n2)if(f[n1][i]>ans)ans=f[n1][i],y=i;
36     t=0;
37     while(f[x][y])
38     {
39         while(a[x]!=b[y]){x--;if(!x)return;}
40         al[ans-t]=b[y],y=lst[x][y],t++;
41     }
42 }
43 int main()
44 {
45     T=read();
46     while(T--)
47     {
48         n1=read();go(i,1,n1)a[i]=read();
49         n2=read();go(i,1,n2)b[i]=read();
50         sol();
51         printf("%d\n",ans);
52         if(ans){go(i,1,ans)printf("%d ",al[i]);printf("\n");}
53     }
54     return 0;
55 }
View Code
posted @ 2019-05-18 15:48  DTTTTTTT  阅读(147)  评论(0编辑  收藏  举报