正题
题目链接:https://www.luogu.com.cn/problem/AT3955
题目大意
nnn个房子在一个坐标轴上,第iii个有pip_ipi个人在位置xix_ixi,开始所有人都在一辆在位置sss的车上,每一时刻,每个人都会投票决定车的走向,票多的赢,求最后一个人的回家时间。
注意每个人不一定会投回家的方向,有可能他会帮助其他乘客下车后再回家更优。
解题思路
我们考虑111和nnn哪个先回家,结论就是如果p1≥pnp_1\geq p_np1≥pn那么111一定先比nnn回家,反之同理。
证明的话就是如果往右走的票多那么等这些票下车后一定有一个时间使得左边比右边多,不然就是直接走右边。
所以这种情况下nnn一定比111晚,那么111早到家就意味着nnn早到家,那么nnn的人就会和111的人投票一样,所以我们可以相当于删去nnn,然后答案加上xn−x1x_n-x_1xn−x1且让p1+=pnp_1+=p_np1+=pn。一直递归下去即可。
时间复杂度O(n)O(n)O(n)
codecodecode
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const ll N=1e5+10;
ll n,s,x[N],p[N],f[N],ans;
ll solve(ll l,ll r,ll last){if(s<x[l])return x[r]-s;if(s>x[r])return s-x[l];if(p[l]<p[r]){p[r]+=p[l];return solve(l+1,r,r)+((last==l)?(x[r]-x[l]):0);}else{p[l]+=p[r];return solve(l,r-1,l)+((last==r)?(x[r]-x[l]):0);}
}
int main()
{scanf("%lld%lld",&n,&s);for(ll i=1;i<=n;i++)scanf("%lld%lld",&x[i],&p[i]);printf("%lld\n",solve(1,n,(p[1]>=p[n])?n:1));
}