最长公共子序列(洛谷)dp

这个与一般求LCS 不太相同,因为N太大, 先前学的是O(n*n),rep(i, n) rep(j, n):

现在N会到1e5,肯定会爆,那可以怎么优化呢?

1.把a数组每个数出现的顺序当做新编号放在num[]数组里,那么b数组就可以随之改变。即a数组变成1 2 3 4 5, 那么b可以相应变成3 2 1 4 5, 那么最长公共子序列显然就变成了求b数组的最长上升子序列。而最长上升子序列又可以用单调队列和二分优化;

2.单调队列:每次找到第一个大于等于b[i]的值的位置与b[i]替换,最终队列的长度就是最大公共子序列的长度;

2.这个方法只能适用于每个序列中没有重复元素的时候;

3.如果有的题b序列中有的数a中可能没有,那么把b序列变完之后记得要把0给去掉(a中没有这个数);

4.需要考虑3情况的,还有更多详细情况的可以看小蓝书P67。

AC代码:

#include<bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define ios ios::sync_with_stdio(false);cin.tie(0); cout.tie(0);
typedef pair<int, int> PII;
const double pi = acos(-1.0);
#define rep(i, n) for (int i = 1; i <= (n); ++i)
#define rrep(i, n) for (int i = n; i >= (1); --i)
typedef long long ll;
#define sqar(x) ((x)*(x))

inline int read() {
	int s = 0, w = 1;
	char ch = getchar();
	while (ch < '0' || ch>'9') { if (ch == '-')w = -1; ch = getchar(); }
	while (ch >= '0' && ch <= '9') s = s * 10 + ch - '0', ch = getchar();
	return s * w;
}

const int N = 1e5 + 10;
int num[N], q[N];

int main(){
  int n, temp;
  n = read();
  rep(i, n){
    temp = read();
    num[temp] = i;
  }
  int res = 1;
  rep(i, n) q[i] = INF;
  rep(i, n){
    temp = read();
    temp = num[temp];
    int k = lower_bound(q + 1, q + 1 + n, temp) - q;
    res = max(res, k);
    q[k] = temp;
  }
  printf("%d", res);
  return 0;
}

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值