AGC023D

题目链接: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)。接下来是证明:

  1. (n=2) 显然成立。
  2. (nge 3)(x_{n-1}<S) 显然除了第 (n) 座建筑的员工,都希望向左走。
  3. (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;
}
原文地址:https://www.cnblogs.com/withhope/p/14242730.html