题意

操作:每次可选一段区间覆盖为原区间最大值。
目标:AB中相等的位尽量多。

思路

每个值只有为 Bi 时才会贡献答案,设 Ai 左边第一个为 Bi 的为 Li ,同理右边的为 Ri,当然还要满足 (Li,i][i,Ri) 的值均 Bi
然后就是突破口:Ai一定由Li或者Ri覆盖过来,因为覆盖区间越少,合法的概率更大,且改动得(后效性)越小。
如果将每个点i向所选的覆盖到的位置(Li/Ri)连边,出现交叉显然是不行的,比如 iLi ,那么 [Li,i) 的点值最终至少是 ALi=Bi 了,所以连向的位置 Li
既然没有交叉,那从前往后匹配就是有序的,DP就好了,每次转移到加入i个的匹配,只需要更新 LiRi 处即可。

code

点击查看代码
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 5;

#define lowbit(x) (x & -(x))

int L[N], R[N], a[N], b[N], st[N], tp, c[N], n;
map<int, int> mp;

void Update(int x, int d) {for(; x <= n; x += lowbit(x)) c[x] = max(c[x], d);}
int Mx(int x) {int mx = 0; for(; x; x -= lowbit(x)) mx = max(mx, c[x]); return mx;}

int main() {
	scanf("%d", &n);
	for(int i = 1; i <= n; i++) {scanf("%d", &a[i]);}
	for(int i = 1; i <= n; i++) {scanf("%d", &b[i]);}
	for(int i = 1; i <= n; i++) {
		while(tp && a[st[tp]] <= a[i]) {mp[a[st[tp--]]] = 0;}
		st[++tp] = i; mp[a[i]] = i;
		L[i] = mp[b[i]];
	}
	tp = 0; mp.clear();
	for(int i = n; i; i--) {
		while(tp && a[st[tp]] <= a[i]) {mp[a[st[tp--]]] = 0;}
		st[++tp] = i; mp[a[i]] = i;
		R[i] = mp[b[i]];
	}
	for(int i = 1; i <= n; i++) {
		int l = Mx(L[i]), r = Mx(R[i]);
		if(L[i]) Update(L[i], l + 1);
		if(R[i]) Update(R[i], r + 1);
	}
	printf("%d\n", Mx(n));
	return 0;
}