[codeforces 1366E] Two Arrays 双指针+乘法原理+注意边界处理

Educational Codeforces Round 89 (Rated for Div. 2)  参与排名人数13281

[codeforces 1366E]   Two Arrays   双指针+乘法原理+注意边界处理

总目录详见https://blog.csdn.net/mrcrack/article/details/103564004

在线测评地址http://codeforces.com/contest/1366/problem/E

ProblemLangVerdictTimeMemory
E - Two Arrays GNU C++17Accepted93 ms1800 KB

做完该题,突然发现快速排序是双指针的鼻祖。

题目大意:将数组a中的连续元素分成m个子数组,要求第1个子数组中的最小值等于b1,第2个子数组中的最小值等于b2,

第3个子数组中的最小值等于b3,依次类推。问满足这种情况的分组,有几种可能。

样例进一步说明如下

6 3
12 10 20 20 25 30
10 20 30

2

第1种情况如下
[12,10,20],[20,25],[30]
[12,10,20]最小值是10,b[1]=10,两者相等
[20,25]最小值是20,b[2]=20,两者相等
[30]最小值是30,b[3]=30,两者相等

第2种情况如下
[12,10],[20,20,25],[30]
[12,10]最小值是10,b[1]=10,两者相等
[20,20,25]最小值是20,b[2]=20,两者相等
[30]最小值是30,b[3]=30,两者相等. 

以下样例处理,可结合代码进行研究

样例1处理如下

6 3
12 10 20 20 25 30
10 20 30

2

ans=1;

b数组位置1  2  3 
b数组数值10 20 30

a数组位置1  2  3  4  5  6
a数组数值12 10 20 20 25 30

逆向搜索
1.处理b[3]
a[6]==b[3],r=6
a[5]<b[3],l=5

乘法原理ans=1*(6-5)=1

2.处理b[2]
a[4]==b[2],r=4
a[2]<b[2],l=2

乘法原理ans=1*(4-2)=2

3.处理b[1]
a[2]==b[1],r=2
a[0]<b[1],l=0

此时没有选择,所有数据都必须归属于地一个分组。


综上所述,结果是2


样例2处理如下

4 2
1 3 3 7
3 7

0

ans=1;

b数组位置1 2 
b数组数值3 7

a数组位置1 2 3 4
a数组数值1 3 3 7

逆向搜索
1.处理b[2]
a[4]==b[2],r=4
a[3]<b[2],l=3

乘法原理ans=1*(4-3)=1

2.处理b[1]
a[3]==b[1],r=4
a[1]<b[1],l=1

因为是第1个分组,还有a[1]元素选不进分组,故分组不存在


综上所述,结果是0


样例3处理如下

8 2
1 2 2 2 2 2 2 2
1 2

7

ans=1;

b数组位置1 2 
b数组数值1 2

a数组位置1 2 3 4 5 6 7 8
a数组数值1 2 2 2 2 2 2 2

逆向搜索
1.处理b[2]
a[8]==b[2],r=8
a[1]<b[2],l=1

乘法原理ans=1*(8-1)=7

2.处理b[1]
a[1]==b[1],r=1
a[0]<b[1],l=0

此时没有选择,所有数据都必须归属于地一个分组。


综上所述,结果是7


AC代码如下

#include <stdio.h>
#define maxn 200010
#define mod 998244353
#define LL long long
int a[maxn],b[maxn],n,m;
LL ans=1;
int main(){
	int i,j,l,r;
	scanf("%d%d",&n,&m);
	for(i=1;i<=n;i++)scanf("%d",&a[i]);
	for(i=1;i<=m;i++)scanf("%d",&b[i]);
	r=n;
	for(i=m;i>=1;i--){//逆向分组
		while(a[r]>b[i])r--;//循环结束时,要么a[r]==b[i];要么a[r]<b[i];要么r==0;注意
		if(a[r]!=b[i]||r==0){ans=0;break;}//表示没找到b[i]
		l=r;
		while(a[l]>=b[i])l--;//循环结束时要么a[l]<b[i];要么l==0;注意
		if(i!=1)ans=ans*(r-l)%mod;//不是第1个分组时,乘法原理,区间[l+1,r]  个数r-(l+1)+1=r-l
		else if(l!=0)ans=0;//i==1
		r=l;//r是正宗右边界
	}
	printf("%lld\n",ans);
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值