P9806 [POI2022~2023R1] poc
P9806 [POI2022~2023R1] poc
题目翻译:
给定一个一序列 \(A\),表示每节车厢的类型,在给出一个一个序列 \(B\),这个序列是从 \(A\) 中可以选出来,求 \(A\) 序列的那些点是可能选到的
思路:
我们阅读题目可以发现,若一个数在 \(A\) 中可以取的话,那他必须保证他在 \(B\) 中左侧的数,在 \(A\) 中左侧也一定要存在。同理可得他在 \(B\) 中右侧的数,在 \(A\) 中右侧也一定要存在。那根据这个性质就可以得到一个解法:
1.我们只需要提前找到,从左开始的最接近的满足条件的位置,和最右边满足条件的位置,预处理出来即可;
2.如何判断这个数是否可选,只需要判断他是否在满足条件的最左边的这个数的位置和最右边这个数的位置间即可
实现:
1.开局先从右往左枚举,由于我们要找的数一定是符合序列 \(B\) 的,所以维护一个当前找到过的数的位置 \(j\) 那直到找到第一个 \(j\) 的值相同地方,在左移找下一个数
int j=m;
for(int i=n;i>=1;i--){
if(a[i]==b[j]){
p[j]=i;
j--;
}
}
2.让后在从左往右找,这次维护当前这个数是从左往右满足的第几个数,若这个数在左边已经满足条件,且他这个数在最右边满足条件的数前面,那这个数就满足条件,就可以直接输出即可
j=1;
for(int i=1;i<=n;i++){
if (a[i]==b[j]){
p2[a[i]]=j;
j++;
}
if (p2[a[i]]!=0 && p[p2[a[i]]]>=i){
cout<<"1 ";
}
else cout<<"0 ";
}
完整代码:
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
int a[N],b[N];
int p[N],p2[N];
int main(){
int n,m,k;
cin>>n>>m>>k;
for(int i=1;i<=n;i++){
cin>>a[i];
}
for(int i=1;i<=m;i++){
cin>>b[i];
}
int j=m;
for(int i=n;i>=1;i--){
if(a[i]==b[j]){
p[j]=i;
j--;
}
}
j=1;
for(int i=1;i<=n;i++){
if (a[i]==b[j]){
p2[a[i]]=j;
j++;
}
if (p2[a[i]]!=0 && p[p2[a[i]]]>=i){
cout<<"1 ";
}
else cout<<"0 ";
}
}
本文作者:XichenOC
本文链接:https://www.cnblogs.com/XichenOC/p/18682401
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
分类:
标签:
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步