题解:P14452 [ICPC 2025 Xi'an R] Follow the Penguins

(为什么还没有人写题解)

Solution

最暴力的方式肯定是直接按时间顺序模拟,但是会因为时间过长而超时,所以我们只在有效的时间点进行操作就好了。

有效的时间点自然是企鹅相遇的时候,那么就可以用一个 \(\mathtt{set}\) 来维护每只企鹅的预计相遇时间,用 \(\mathtt{vector}\) 数组来统计每只企鹅是哪些企鹅的目标。初始时只有和目标企鹅相向走的企鹅有预计时间,并且这个时间就是它最后的答案,而同向的预计时间先设为无穷大。每次取 \(\mathtt{set}\) 中时间最小的企鹅,计算出它相遇时停止的位置,得到以这只企鹅为目标的所有企鹅的预计时间,并在 \(\mathtt{set}\) 中更新这些企鹅的预计时间即可。

Code

#include<bits/stdc++.h>
using namespace std;
namespace io{(快读)}using namespace io;
const int N=5e5+5;
int n,now,t[N],a[N],w[N],nowt[N],ans[N];
vector<int>p[N];
set<pair<int,int>>S;
int main(){
	read(n);
	for(int i=1;i<=n;i++){
		read(t[i]);
		p[t[i]].push_back(i);
	}
	for(int i=1;i<=n;i++)a[i]=read()*2;//乘2避免小数
	for(int i=1;i<=n;i++)w[i]=(a[i]<=a[t[i]]);//每只企鹅移动方向
	for(int i=1;i<=n;i++){
		nowt[i]=((w[i]^w[t[i]])?abs(a[i]-a[t[i]])/2:(int)2e9);//预计时间
		S.insert(make_pair(nowt[i],i));
	}
	while(!S.empty()){
		int ti=S.begin()->first,x=S.begin()->second;
		S.erase(S.begin());
		now=ti;//当前时刻
		ans[x]=now;
		int posx=(w[x]?a[x]+now:a[x]-now);//停止位置
		for(int y:p[x]){
			auto iy=S.find(make_pair(nowt[y],y));
			if(iy==S.end())continue;
			S.erase(iy);
			int posy=(w[y]?a[y]+now:a[y]-now);//此时这只企鹅的位置
			nowt[y]=now+abs(posx-posy);
			S.insert(make_pair(nowt[y],y));//更新
		}
	}
	for(int i=1;i<=n;i++)writesp(ans[i]);
	return 0;
}
posted @ 2025-11-16 22:33  ADay526  阅读(26)  评论(0)    收藏  举报