P8889 [入门赛 #7] 狠狠地切割 (Hard Version)

题目描述

现给你一个长度为 n 的序列a1​,⋯,an​ 和 �m 个互不相同的整数 b1​,⋯,bm​。你需要按照这 m 个数对序列 a 进行狠狠地切割

具体的,对于一个数字 ∈[1,n],如果存在一个整数 j∈[1,m],使得 ai​=bj​,则将位置 i 称为一个切割点。对序列 a 中的每一个切割点,我们在这个位置进行一次狠狠地切割。方法是,将该位置的数字去除,然后在这个位置将其左右的序列/片段一分两半。

如果对狠狠地切割的定义有疑问,可以参照「样例 #1」及「样例解释 #1」进行理解。

你需要计算,在进行了所有可能的狠狠地切割后,序列被切割为了多少片段

特别的,如果在切割后,某一段内没有数组,那这一段不可被叫做片段。同样的,如果 1 或 n 为切割点,其与开头和结尾之间也不存在片段。

如果对片段的概念有疑问,可以参照「样例 #2」及「样例解释 #2」进行理解。

输入格式

第一行为两个整数,依次表示序列 a 的长度 n 和序列 b 的长度 m。
第二行有 n 个整数,第 i 个整数表示 ai​。
第三行有 m 个整数,第 i 个整数表示 bi​。

输出格式

输出一个整数,代表狠狠地切割后的片段的个数。

输入输出样例

输入 #1

6 2
3 4 3 5 2 6
5 4

输出 #1

3

输入 #2

6 3
3 4 3 5 2 6
3 5 6

输出 #2

2
#include<bits/stdc++.h>
using namespace std;
long long n,m,x,a[500005],b[500005],ans;
bool check(long long k) {
	long long l=1,r=m,mid;
	while(l<=r){
		mid=(l+r)/2;
		if (k<b[mid])r=mid-1;
		else if(k>b[mid])l=mid+1;
		else return 1;
	}
	return 0;
}
int main(){
	cin>>n>>m;
	for(int i=1;i<=n;i++)scanf("%lld",&a[i]);
	for(int i=1;i<=m;i++)scanf("%lld",&b[i]);
	sort(b+1,b+m+1);
	if(!check(a[n]))ans++;
	for(int i=1;i<n;i++){
		if(!check(a[i])&&check(a[i+1]))ans++;
	}
	cout<<ans;
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值