题意
操作:每次可选一段区间覆盖为原区间最大值。
目标:和中相等的位尽量多。
思路
每个值只有为 时才会贡献答案,设 左边第一个为 的为 ,同理右边的为 ,当然还要满足 和 的值均 。
然后就是突破口:一定由或者覆盖过来,因为覆盖区间越少,合法的概率更大,且改动得(后效性)越小。
如果将每个点向所选的覆盖到的位置()连边,出现交叉显然是不行的,比如 连 ,那么 的点值最终至少是 了,所以连向的位置 。
既然没有交叉,那从前往后匹配就是有序的,DP就好了,每次转移到加入个的匹配,只需要更新 和 处即可。
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;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· winform 绘制太阳,地球,月球 运作规律
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人