1. 程式人生 > 其它 >攀爬

攀爬

攀爬

題面:

我們把蝸牛上下爬樹抽象成 \(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;
}
路漫漫其修遠兮,吾將上下而求索。