欲望以提升热忱,毅力以磨平高山!|

XichenOC

园龄:1个月粉丝:4关注:0

2025-01-20 19:32阅读: 4评论: 0推荐: 0

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 中国大陆许可协议进行许可。

posted @   XichenOC  阅读(4)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起