列表

详情


NC239211. 弹珠碰撞

描述

在一条长度为 n 的线段上,有 m 颗弹珠在匀速左右滚动,在 1 单位时间内,每颗弹珠能滚动 1 单位距离。第 i 颗弹珠由两个参数 d_i,p_i 描述,d_i 是一个值为 01 的整数,表示弹珠初始向左滚动/向右滚动;p_i 是一个 1n 之间的正整数,表示弹珠初始从线段上 p_i 位置出发。

由于只有一条线段,两颗滚动方向相反的弹珠位置重合的时候就会停滞 1 单位时间不滚动,并交换两颗弹珠滚动的方向。需要注意的是,一颗弹珠可以反复发生碰撞,如果在停滞中受到碰撞,则停滞时间会累加。

如果一颗弹珠滚到了位置 0 或位置 ,那么这颗弹珠就滚出了线段。请问最后一颗弹珠在什么时候滚出线段?可以证明所有弹珠都会在某个整数时刻滚出线段。


输入描述

第一行,两个整数 n,m ,分别表示线段长度和弹珠数量。

第二行,m 个整数,第 i 个整数表示 d_i

第三行,m 个整数,第 i 个整数表示 p_i,保证 p_i 两两不同。


输出描述

一行一个整数,表示最后一颗弹珠滚出线段的时刻。

示例1

输入:

2 2
0 1
1 2

输出:

1

示例2

输入:

3 2
1 0
1 3

输出:

4

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++(g++ 7.5.0) 解法, 执行用时: 389ms, 内存消耗: 19288K, 提交时间: 2022-11-08 18:53:12

#include <iostream>
#define int long long
using namespace std;
const int N=2e6+10;
int n,m,d[N],p[N],dp[N],max1;
signed main()
{
	cin>>n>>m;
	for(int i=1;i<=m;i++) cin>>d[i];
	for(int i=1;i<=m;i++) cin>>p[i],dp[p[i]]=d[i]+1;
	int l=0,r=0;
	for(int i=1;i<=n;i++)
	{
		if(dp[i]==0) continue;
		if(dp[i]==1) max1=max(max1,i+r);
		else r++;
	}
	for(int i=n;i>=1;i--)
	{
		if(dp[i]==0) continue;
		if(dp[i]==2) max1=max(max1,n-i+1+l);
		else l++;
	}
	cout<<max1<<"\n";
	return 0;
}

Python3 解法, 执行用时: 1383ms, 内存消耗: 90756K, 提交时间: 2022-10-30 20:21:31

n,m=map(int,input().split())
d=list(map(int,input().split()))
p=list(map(int,input().split()))
left,right,pos=[0]*(n+5),[0]*(n+5),[-1]*(n+5)
for i in range(m):
    pos[p[i]]=d[i]
for i in range(1,n+2):
    left[i]=left[i-1]
    if pos[i]==1:
        left[i]+=1
for i in range(n+2,-1,-1):
    right[i]=right[i+1]
    if pos[i]==0:
        right[i]+=1
ans=0
for k in p:
    if pos[k]==0:
        ans=max(ans,left[k]+k)
    else:
        ans=max(ans,n+1-k+right[k])
print(ans)

pypy3 解法, 执行用时: 828ms, 内存消耗: 125904K, 提交时间: 2022-10-29 15:50:07

n,m=map(int,input().split())
d=list(map(int,input().split()))
p=list(map(int,input().split()))
left,right,pos=[0]*(n+5),[0]*(n+5),[-1]*(n+5)
for i in range(m):
    pos[p[i]]=d[i]
for i in range(1,n+2):
    left[i]=left[i-1]
    if pos[i]==1:
        left[i]+=1
for i in range(n+2,-1,-1):
    right[i]=right[i+1]
    if pos[i]==0:
        right[i]+=1
ans=0
for k in p:
    if pos[k]==0:
        ans=max(ans,left[k]+k)
    else:
        ans=max(ans,n+1-k+right[k])
print(ans)

C++(clang++ 11.0.1) 解法, 执行用时: 387ms, 内存消耗: 27444K, 提交时间: 2022-10-28 20:06:43

#include<bits/stdc++.h>
using namespace std;
long long n,m,a[1000001],b[1000001],c[1000001],d[1000001],s,i;
int main()
{
	cin>>n>>m;
	for(i=1;i<=m;i=i+1)cin>>a[i];
	for(i=1;i<=m;i=i+1)
	{
		cin>>b[i];
		if(a[i]==0)++c[b[i]];else ++d[b[i]];
	}
	for(i=n;i>=1;i=i-1)c[i]=c[i]+c[i+1];
	for(i=1;i<=n;i=i+1)d[i]=d[i]+d[i-1];
	for(i=1;i<=m;i=i+1)
	{
		if(a[i]==0)s=max(s,b[i]+d[b[i]]);
		else s=max(s,n+1-b[i]+c[b[i]]);
	}
	cout<<s;
	return 0;
}

上一题