把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

题解 P7169 [eJOI2020 Day1] Exam

传送门

题意

有两个长度为 N 的数列 AiBi。可以对 A 数组进行若干次操作,每次可以使 AiAj 中的所有数变成期间的最大值,求最多能使多少个数满足要求。

分析

显然,要使我们的某一个 Ax 变成 Bx,至少会包含 ALxARxLxx 左侧(包括自己)的与 Bx 相等的第一个的下标,Rxx 右侧(包括自己)的与 Bx 相等的第一个的下标。

但是这还有一个条件,那就是 Lxi 之间没有大于 Bx 的数字,Rx 相似。

解决了 LxRx 的计算,我们借用这两个数组来解决我们的答案。

形象化的,我们将某一组操作变成一条线段。由上方点 i 连向下方 LiRi 的一条边。

并且线与线之间不能相交。

由此,我们可以定义一个数组,fi,j 表示上方到达 i 点,下方到达 j 点的最多条数。

可以得到转移式:fi,j=maxk=1kjfi1,k+1

我们可以利用树状数组来解决。

Code。

#include <bits/stdc++.h>
#include <vector>
//#define int long long
using namespace std;
const int N = 2e5+5;
inline int read() {
int x;
scanf("%d",&x);
return x;
}
int n, m,a[N],b[N],num[N],L[N],R[N],st[N][20],lg[N];
inline void lsh() {
int cnt=0;
for(int i=1; i<=n; ++i) num[++cnt]=a[i];
for(int i=1; i<=n; ++i) num[++cnt]=b[i];
sort(num+1,num+cnt+1);
cnt=unique(num+1,num+cnt+1)-num-1;
for(int i=1; i<=n; ++i) a[i]=lower_bound(num+1,num+cnt+1,a[i])-num;
for(int i=1; i<=n; ++i) b[i]=lower_bound(num+1,num+cnt+1,b[i])-num;
}
vector<int > pos[N];
struct Bit {
int c[N+2];
inline int lowbit(int x) {
return x&-x;
}
inline void change(int x,int y) {
for(int i=x; i<=N; i+=lowbit(i)) c[i]=max(c[i],y);
}
inline int query(int x) {
int tot=0;
for(int i=x; i; i-=lowbit(i)) tot=max(tot,c[i]);
return tot;
}
} bit;
inline int query(int l,int r) {
return max(st[l][lg[r-l+1]],st[r-(1<<lg[r-l+1])+1][lg[r-l+1]]);
}
signed main() {
n=read();
for(int i=1; i<=n; ++i) a[i]=read();
for(int i=1; i<=n; ++i) b[i]=read();
lsh();
for(int i=1; i<=n; ++i) st[i][0]=a[i];
for(int i=2; i<N; ++i) lg[i]=lg[i/2]+1;
for(int i=1; i<20; ++i) for(int j=1; j+(1<<i)-1<=n; ++j) st[j][i]=max(st[j][i-1],st[j+(1<<i-1)][i-1]);
for(int i=1; i<=n; ++i) pos[a[i]].push_back(i);
for(int i=1; i<=n; ++i) {
if(b[i]<a[i]) continue;
L[i]=upper_bound(pos[b[i]].begin(),pos[b[i]].end(),i)-pos[b[i]].begin()-1;
if(L[i]>=0) L[i]=pos[b[i]][L[i]];
else L[i]=0;
if(L[i]&&query(L[i],i)>b[i]) L[i]=0;
R[i]=lower_bound(pos[b[i]].begin(),pos[b[i]].end(),i)-pos[b[i]].begin();
if(R[i]<pos[b[i]].size()) R[i]=pos[b[i]][R[i]];
else R[i]=0;
if(R[i]&&query(i,R[i])>b[i]) R[i]=0;
}
for(int i=1; i<=n; ++i) {
int l=bit.query(L[i]),r=bit.query(R[i]);
if(R[i]) bit.change(R[i],r+1);
if(L[i]) bit.change(L[i],l+1);
}
cout<<bit.query(n);
return 0;
}
posted @   djh0314  阅读(8)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
浏览器标题切换
浏览器标题切换end
点击右上角即可分享
微信分享提示