题意: 在一条直线上 到每个点pi 个人,位置xi 。 建一个中转站 ,每个位置上的 不高兴 的值 就是 pi*( xi - X) ,X 为 中转站。问不高兴的值的总和最小是多少。
对一个位置 向两边的变化速率的分析的。 一个点向右的速率是 左侧人数和 减去 右侧人数和。随着点从左端向右端移动的过程中 速率由负值一直增大, 则总和的变化就是 下凸曲线,就是三分曲线。
#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <stack>
#include <cstring>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <assert.h>
#include <queue>
#define REP(i,n) for(int i=0;i<n;i++)
#define TR(i,x) for(typeof(x.begin()) i=x.begin();i!=x.end();i++)
#define ALLL(x) x.begin(),x.end()
#define SORT(x) sort(ALLL(x))
#define CLEAR(x) memset(x,0,sizeof(x))
#define FILLL(x,c) memset(x,c,sizeof(x))
using namespace std;
const double eps = 1e-9;
#define LL long long
#define pb push_back
const int maxn = 110000;
int x[maxn], p[maxn];
int n;
int l,r;
double f(double a){
double ans = 0 ;
for(int i=1;i<=n;i++){
ans += fabs(a-x[i])*p[i];
}
return ans;
}
void solve(){
double left = l;
double right = r;
while(right - left >1e-9){
double lmid = (left +right )/2;
double rmid = (lmid + right)/2;
if(f(lmid)> f(rmid)){
left = lmid ;
}else{
right =rmid;
}
}
printf("%.5f\n",left);
// cout <<f(3)<<endl;
// cout << f(2)<<endl;
}
int main(){
while(~scanf("%d",&n)){
for(int i=1;i<=n;i++){
scanf("%d%d",&x[i],&p[i]);
if(i==1){
l =r = x[i];
}else{
l = min(x[i],l);
r = max(x[i],r);
}
}
solve();
}
return 0;
}