攀爬

攀爬

题面:

我们把蜗牛上下爬树抽象成 \(m\) 只蜗牛在一条长度为 \(n\) 的线段上匀速左右爬行

线段上共有 \(n\) 个位置,分别记为 \(1,2,\cdots ,n\)

\(1\) 单位时间内,每只蜗牛能爬行 \(1\) 单位距离。

\(i\) 只蜗牛有一个初始方向 \(d_i\) ,这个方向的值只可能是 \(0\)\(1\) ,分别表示它初始向左,向右爬行。

\(i\) 只蜗牛还有一个初始位置 \(p_i\),表示它初始从线段上 \(p_i\) 的位置出发,保证 \(1\leq p_i\leq n\)

如果一只蜗牛爬行到了线段的 \(0\)\(n+1\) 位置,则称这只蜗牛爬出了线段。

但是由于只有一条线段,方向相反的蜗牛在碰撞到一起时会停顿一秒并交换它们的方向继续爬行。

需要注意的是:

  • 相同方向的蜗牛 不会 发生碰撞,并且一只蜗牛在停顿的时候被方向相反的蜗牛碰撞,停顿时间会 累加
  • 一只蜗牛 可以 反复发生碰撞。

可以证明在这样的条件下,经过一段时间,所有的蜗牛都会爬出线段,并且每只蜗牛爬出线段的时刻都可以用一个整数表示。

摸鱼酱被小小的蜗牛整懵了,他希望你能告诉他,最后一只蜗牛在哪个时刻爬出了线段。

\(1\le m\le n\le 10^6,d_i\in\text{{0,1}},1\le p_i\le n\)


思维题。

由于蜗牛相撞后只是方向改变,同时这道题中蜗牛并没有编号,所以当两只蜗牛相撞,我们可以等效的看做两只蜗牛停顿一秒后继续向原来的方向爬行。

那么每只蜗牛的走出时间就是相撞的蜗牛数加没有蜗牛影响时他走出线段的时间。根据我们上面的等效模型,相撞的蜗牛数就是初始位置大于/小于他的,且方向相反的蜗牛数。

可以用前缀和在 \(O(n)\) 的时间内求解。

代码如下:

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 1e6+5;
int n,m,S[2][MAXN],D[MAXN],P[MAXN];
int main()
{
	scanf("%d %d",&n,&m);
	for(int i=1;i<=m;++i) scanf("%d",&D[i]);
	for(int i=1;i<=m;++i) scanf("%d",&P[i]);
	for(int i=1;i<=m;++i) S[D[i]][P[i]]++;
	for(int i=1;i<=n;++i) S[1][i]+=S[1][i-1]; 
	for(int i=n;i>=1;--i) S[0][i]+=S[0][i+1];
	int ans=0;
	for(int i=1;i<=m;++i)
	{
		if(D[i]) ans=max(ans,n+1-P[i]+S[0][P[i]]);
		else ans=max(ans,P[i]+S[1][P[i]]);
	}
	printf("%d\n",ans);
	return 0;
}
posted @ 2021-11-18 21:30  夜空之星  阅读(246)  评论(0编辑  收藏  举报