CF463D Gargari and Permutations (LCS)

这题的主要信息就是,这是一个排列,而不是数列

对于排列也就是说每行都是1-n这些数,只是位置不同,我们观察到n只有1000

并且考虑到对于一个最长公共子序列,也就是说,如果两个数能成为公共子序列,那么其中一个数在每一行都是在另一个数后面

所以我们设计dp状态f[i]表示以i结尾的最长公共子序列,在转移的时候,只有出现了k次才可以转移,并且要从前面已经存在的f[j]转移过来,不然就是1,并且每行的j都在每行的i前面

#include<iostream>
#include<cstring>
#include<cstdio>
#include<map>
#include<algorithm>
#include<queue>
#include<set>
#define ull unsigned long long
using namespace std;
typedef long long ll;
typedef pair<int,int> pll;
const int N=1e5+10;
int f[N];
int pos[6][N];
int a[6][N];
int cnt[N];
vector<int> num;
int main(){
    int n,k;
    cin>>n>>k;
    int i;
    int j;
    for(i=1;i<=k;i++){
        for(j=1;j<=n;j++){
            scanf("%d",&a[i][j]);
        }
    }
    int res=0;
    for(i=1;i<=n;i++){
        for(j=1;j<=k;j++){
            int sign=a[j][i];
            cnt[sign]++;
            pos[j][sign]=i;
            if(cnt[sign]==k){
                int l;
                if(num.empty()){
                    f[sign]=1;
                }
                else{
                    for(l=0;l<num.size();l++){
                        int r;
                        int flag=0;
                        for(r=1;r<=k;r++){
                            if(pos[r][sign]<pos[r][num[l]]){
                                flag=1;
                                break;
                            }
                        }
                        if(flag)
                            f[sign]=max(f[sign],1);
                        else{
                            f[sign]=max(f[sign],f[num[l]]+1);
                        }
                    }

                }
                num.push_back(sign);
                res=max(res,f[sign]);
            }
        }
    }
    cout<<res<<endl;
    return 0;
}
View Code

猜你喜欢

转载自www.cnblogs.com/ctyakwf/p/12637274.html
LCS