P1439 【模板】最长公共子序列

题目链接


对于这道题,我们可以把 P1 改为 1,2,3,...,n 这样一个序列,让 P1 的数一一与新的序列映射,{3,2,1,4,5}{1,2,3,4,5}

然后我们把这个映射用于 P2{1,2,3,4,5}{3,2,1,4,5}

那么我们就将问题转化为了,如何求映射后的 P2 的 LIS,我们可以一步一步进行优化,这里有两个方法,一个是树状数组优化,另一个可以用二分。

树状数组优化

fi=maxj=1&aj<aii1fj

max 有两个限制,一个是 j<i 另一个是 aj<ai 首先前者是肯定满足的,因为我们是从小到大来的,那么第二个我们就可以用树状数组维护了。

#include <cstring>
#include <vector>
#include <iostream>
#include <algorithm>

using namespace std;

namespace oi{
	using ll = long long;
	using ull = unsigned long long;
	using pii = pair<int, int>;
	using db = double;
	using pll = pair<ll, ll>;
	#define gc getchar
	#define pc putchar
	#define endl '\n'

	inline ll read() {
		char ch = gc(); ll fu = 0, s = 0;
		while(!isdigit(ch)) fu |= (ch == '-'), ch = gc();
		while(isdigit(ch)) s = (s << 1) + (s << 3) + (ch ^ 48), ch = gc();
		return fu ? -s : s;
	}

	template <typename T>
	inline void write(T x, char ch) {
		if(x < 0) pc('-'), x = -x;
		static int stk[30];
		int tt = 0;
		do stk[++tt] = x % 10, x /= 10; while(x);
		while(tt) pc(stk[tt--] ^ 48);
		pc(ch);
	}

	template <typename T>
	inline void write(T x) {
		if(x < 0) pc('-'), x = -x;
		static int stk[30];
		int tt = 0;
		do stk[++tt] = x % 10, x /= 10; while(x);
		while(tt) pc(stk[tt--] ^ 48);
	}
};
using namespace oi;
const int MAXN = 1e5 + 10;
int n, f[MAXN], a, b[MAXN], t[MAXN];
int c[MAXN];

inline int lowbit(int x) {
	return x & -x;
}

int ask(int x) {
	int res = 0;
	for (;x; x -= lowbit(x)) res = max(res, c[x]);
	return res;
}

void modify(int x, int y) {
	for (; x <= n; x += lowbit(x)) c[x] = max(c[x], y);
}

void solve() {
	n = read();
	for (int i = 1; i <= n; i++)
		a = read(), t[a] = i;
	for (int i = 1; i <= n; i++)
		b[i] = t[read()];
	int ans = 0;
	for (int i = 1; i <= n; i++) {
		f[i] = ask(b[i] - 1) + 1;
		modify(b[i], f[i]);
		ans = max(ans, f[i]);
	}
	write(ans, '\n');
}

int main() {
	// freopen("test.in", "r", stdin);
	// freopen("test.out", "w", stdout);

	int T = 1;
	// T = read();
	while(T--) solve();
	return 0;
} 

二分

关于二分

#include <cstring>
#include <vector>
#include <iostream>
#include <algorithm>

using namespace std;

namespace oi{
	using ll = long long;
	using ull = unsigned long long;
	using pii = pair<int, int>;
	using db = double;
	using pll = pair<ll, ll>;
	#define gc getchar
	#define pc putchar
	#define endl '\n'

	inline ll read() {
		char ch = gc(); ll fu = 0, s = 0;
		while(!isdigit(ch)) fu |= (ch == '-'), ch = gc();
		while(isdigit(ch)) s = (s << 1) + (s << 3) + (ch ^ 48), ch = gc();
		return fu ? -s : s;
	}

	template <typename T>
	inline void write(T x, char ch) {
		if(x < 0) pc('-'), x = -x;
		static int stk[30];
		int tt = 0;
		do stk[++tt] = x % 10, x /= 10; while(x);
		while(tt) pc(stk[tt--] ^ 48);
		pc(ch);
	}

	template <typename T>
	inline void write(T x) {
		if(x < 0) pc('-'), x = -x;
		static int stk[30];
		int tt = 0;
		do stk[++tt] = x % 10, x /= 10; while(x);
		while(tt) pc(stk[tt--] ^ 48);
	}
};
using namespace oi;
const int MAXN = 1e5 + 10, INF = 0x3f3f3f3f;
int n, f[MAXN], a, b[MAXN], t[MAXN];
int c[MAXN], cnt;

void solve() {
	n = read();
	for (int i = 1; i <= n; i++) a = read(), t[a] = i;
	for (int i = 1; i <= n; i++) b[i] = t[read()];
	c[0] = -INF;
	for (int i = 1; i <= n; i++) {
		if (c[cnt] < b[i]) c[++cnt] = b[i];
		else {
			int l = 1, r = cnt;
			while (l < r) {
				int mid = l + r >> 1;
				if (c[mid] > b[i]) r = mid;
				else l = mid + 1;
			}
			c[l] = b[i];
		}
	}
	write(cnt, '\n');
}

int main() {
	// freopen("test.in", "r", stdin);
	// freopen("test.out", "w", stdout);

	int T = 1;
	// T = read();
	while(T--) solve();
	return 0;
} 
posted @   wh2011  阅读(22)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示