• [codevs2185]最长公共上升子序列


    [codevs2185]最长公共上升子序列

    试题描述

    熊大妈的奶牛在小沐沐的熏陶下开始研究信息题目。小沐沐先让奶牛研究了最长上升子序列,再让他们研究了最长公共子序列,现在又让他们要研究最长公共上升子序列了。
    小沐沐说,对于两个串A,B,如果它们都包含一段位置不一定连续的数字,且数字是严格递增的,那么称这一段数字是两个串的公共上升子串,而所有的公共上升子串中最长的就是最长公共上升子串了。
    奶牛半懂不懂,小沐沐要你来告诉奶牛什么是最长公共上升子串。不过,只要告诉奶牛它的长度就可以了。

    输入

    第一行N,表示A,B的长度。
    第二行,串A。
    第三行,串B。

    输出

    输出长度。

    输入示例

    4
    2 2 1 3
    2 1 2 3

    输出示例

    2

    数据规模及约定

    1<=N<=3000,A,B中的数字不超过maxlongint

    题解

    首先果断想一个 n2logn 的做法:令 f(i, j) 表示考虑了第一个串的前 i 位,第二个串的前 j 位,最长公共上升子序列的末位是 B[j] 的最长公共上升子序列长度;那么如果 A[i] = B[j],就是所有满足 B[k] < B[j] 且 k < j 的 f(i-1, k) 转移到 f(i, j),否则 f(i, j) = f(i-1, j),于是我们可以随着 j 的递增将所有 f(i-1, j) 扔进树状数组,每次转移时查询一下前缀最大值就好了。

    然后发现 n2 做法更 SB:由于我们每次在树状数组上询问的前缀都是 [1, A[i] ](因为只有当 A[i] = B[j] 时才会有转移),所以直接用一个变量存满足 B[k] < A[i] 且 k < j 的 f(i-1, k) 的最大值就好了。注意这里要用滚动数组,滚动数组用起来很方便,因为所有没更新过的 f(i, j) 就等于 f(i-1, j),所以 i 每加 1,直接在上一个版本的滚动数组上做就行了。

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cctype>
    #include <algorithm>
    using namespace std;
    
    const int BufferSize = 1 << 16;
    char buffer[BufferSize], *Head, *Tail;
    inline char Getchar() {
    	if(Head == Tail) {
    		int l = fread(buffer, 1, BufferSize, stdin);
    		Tail = (Head = buffer) + l;
    	}
    	return *Head++;
    }
    int read() {
    	int x = 0, f = 1; char c = Getchar();
    	while(!isdigit(c)){ if(c == '-') f = -1; c = Getchar(); }
    	while(isdigit(c)){ x = x * 10 + c - '0'; c = Getchar(); }
    	return x * f;
    }
    
    #define maxn 3010
    
    int n, A[maxn], B[maxn], f[maxn];
    
    int main() {
    	n = read();
    	for(int i = 1; i <= n; i++) A[i] = read();
    	for(int i = 1; i <= n; i++) B[i] = read();
    	
    	int ans = 0;
    	for(int i = 1; i <= n; i++) {
    		int mx = 0;
    		for(int j = 1; j <= n; j++) {
    			if(B[j] < A[i]) mx = max(mx, f[j]);
    			if(A[i] == B[j]) f[j] = max(f[j], mx + 1);
    			ans = max(ans, f[j]);
    		}
    	}
    	
    	printf("%d
    ", ans);
    	
    	return 0;
    }
    

    当然这题 n2logn 也是能过的。据说有人 n3 大力过去了。。。

  • 相关阅读:
    秋季总结
    PTA第一个编程题总结
    秋季学习总结
    人生路上对我影响最大的三位老师
    自我介绍
    真实的我——自我介绍
    学习总结
    寒假编程总结三
    寒假编程总结二
    寒假编程总结一
  • 原文地址:https://www.cnblogs.com/xiao-ju-ruo-xjr/p/7276943.html
Copyright © 2020-2023  润新知