题意
操作:每次可选一段区间覆盖为原区间最大值。
目标:\(A\)和\(B\)中相等的位尽量多。
思路
每个值只有为 \(B_i\) 时才会贡献答案,设 \(A_i\) 左边第一个为 \(B_i\) 的为 \(L_i\) ,同理右边的为 \(R_i\),当然还要满足 \((L_i,i]\) 和 \([i,R_i)\) 的值均 \(\le B_i\) 。
然后就是突破口:\(A_i\)一定由\(L_i\)或者\(R_i\)覆盖过来,因为覆盖区间越少,合法的概率更大,且改动得(后效性)越小。
如果将每个点\(i\)向所选的覆盖到的位置(\(L_i / R_i\))连边,出现交叉显然是不行的,比如 \(i\) 连 \(L_i\) ,那么 \([L_i,i)\) 的点值最终至少是 \(A_{L_i}=B_i\) 了,所以连向的位置 \(\le L_i\) 。
既然没有交叉,那从前往后匹配就是有序的,DP就好了,每次转移到加入\(i\)个的匹配,只需要更新 \(L_i\) 和 \(R_i\) 处即可。
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;
}