题目链接:D - Go Home
题目大意:一条街上有 (n) 个建筑,坐标分别为 (x_1,x_2,dots,x_n),第 (i) 个建筑是 (p_i) 个员工的家,有一辆车,开始是在 (S),里面乘坐着所有的员工,每一次员工会进行投票决定车想左还是右,员工们的投票策略是使得自己的回家时间最早。如果票一样多,向左行驶,如果一个员工投左、右时间一样长,投左,问所有员工到家的最晚时间。
题解:如果 (x_1<S<x_n),则考虑 (1) 和 (n) 号建筑,先给出结论:若 (p_1ge p_n) 则车会前往 (1) 否则会前往 (n)。接下来是证明:
- 若 (n=2) 显然成立。
- 若 (nge 3) 且 (x_{n-1}<S) 显然除了第 (n) 座建筑的员工,都希望向左走。
- 若 (nge 3) 且 (x_{n-1}>S) 则若到达第 (1) 座建筑前为到达第 (n-1) 座建筑,则结论显然成立,否则转换为前两种情况。
所以说车一定是先前往 (1) 号楼,然后在一路跑到 (n)。
那么 (n) 号楼员工回家的时间就是 (1) 号楼员工回家的时间加上 (x_n-x_1)。
所以说第 (n) 栋楼的员工一定会和第一栋楼的员工投一样的票。
(p_1>p_n) 同理。
所以直接递归,直到 (x_1<S<x_n) 的条件不满足为止,这可以直接算了。
时间复杂度:(O(n))。
#include <cstdio>
typedef long long ll;
const int Maxn=100000;
int n;
int x[Maxn+5],s;
ll p[Maxn+5];
ll calc(int left,int right,int t){
if(s<x[left]){
return x[right]-s;
}
if(s>x[right]){
return s-x[left];
}
if(p[left]>=p[right]){
p[left]+=p[right];
return calc(left,right-1,left)+(t==right?x[right]-x[left]:0);
}
else{
p[right]+=p[left];
return calc(left+1,right,right)+(t==left?x[right]-x[left]:0);
}
}
int main(){
scanf("%d%d",&n,&s);
for(int i=1;i<=n;i++){
scanf("%d%lld",&x[i],&p[i]);
}
printf("%lld
",calc(1,n,p[1]<p[n]?1:n));
return 0;
}