题目
题目链接:https://atcoder.jp/contests/agc023/tasks/agc023_d
一条街上有 (N) 栋楼,位置从小到大分别在 (X_1, X_2, ldots , X_N)。
在位置 (S) 有一座公司,员工下班时乘坐公司的员工班车回家。
这些员工住在 (N) 栋楼内,具体地说,第 (i) 栋楼内住着 (P_i) 个员工。
班车是自动驾驶的,每一个时刻,还在车内的每个员工都会进行投票,只能投正方向或者负方向,不能弃权。
班车会自动统计两个方向的票数,并且往票多的方向行驶一个单位长度,如果票一样多,那就往负方向行驶。
员工们也有投票策略,每一个员工都会投能让他回家时间尽量早的方向,如果两个方向一样早,那就投负方向。
如果班车到达了某一个楼,那么住在那栋楼中的所有员工都会下车。
可以证明,在上述条件下,每个员工投票的方向是能够唯一确定的,班车的运行路线也能够唯一确定。
最终询问最后一名员工回到家,经过了多少个单位时间。可以证明答案在 long long
范围内。
(1 le N le {10}^5),(1 le X_1 < X_2 < cdots < X_N le {10}^9),(1 le P_i le {10}^9),(1 le S le {10}^9),(S
e X_i)。
思路
考虑住在最左右两端的人,假设左端的人数比右端的人数多。那么显然列车一定会在开到最左端后再开到最右端。
那么为了尽快到家,最右端的人一定会想办法让列车在最早的时间内到达最左。所以他们其实就是等价于最左端的人了。
那么就一直这样缩小范围,直到某一段的所有人都移动到另一端。
时间复杂度 (O(n))。
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=100010;
int n,s;
ll ans,a[N],b[N];
int main()
{
scanf("%d%d",&n,&s);
for (int i=1;i<=n;i++)
scanf("%lld%lld",&a[i],&b[i]);
for (int i=1,j=n;a[i]<s || a[j]>s;)
{
if (a[i]>s) { ans+=a[j]-s; break; }
if (a[j]<s) { ans+=s-a[i]; break; }
ans+=a[j]-a[i];
if (b[i]>=b[j])
while (b[i]>=b[j] && a[j]>s) b[i]+=b[j],j--;
else
while (b[i]<b[j] && a[i]<s) b[j]+=b[i],i++;
}
printf("%lld",ans);
return 0;
}