rt
#include <bits/stdc++.h>
#define maxn 20010
#define down 0.9999900001
using namespace std;
const double eps = 1e-5;
int sd[maxn] = {0}; //表示距离前缀和
int sw[maxn] = {0}; //表示重量前缀和
int S[maxn] = {0};
int tmp[maxn];
//bool fac[maxn]; //表示每个工厂与哪颗树重合,注意:在山脚下的锯木厂新建一个不存在的树,不然碰到无法判定
//其实不用链表
int best = 0x3f;
int n;
int getsum(int l,int r){
int dis = sd[r] - sd[l],weight = sw[l];
return (S[r] - S[l] - dis * weight);
}
int calc(int x,int y) {
if(x > y) swap(x,y);
return S[x] + getsum(x,y) + getsum(y,n);
}
//注意:最后一颗树可能和锯木厂是重合的
void SA() {
int last = 0x3f;
double T = 1000;
while (T > eps) {
int t1 = rand() % n + 1;
int t2 = rand() % n + 1;
while(t1 == t2){
t1 = rand() % n + 1;
t2 = rand() % n + 1;
}
int num = calc(t1,t2);
// cout << num << endl;
if(num - last < 0){ //接受最优解
last = num;
best = min(best, last);
}else if(exp(-(num - last) * T) * RAND_MAX > rand()){
last = num;
}
T *= down;
}
}
int w,d,dl;
int main() {
srand((unsigned)time(NULL));
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
scanf("%d %d", &w, &d);
sw[i] = sw[i - 1] + w;
sd[i] = sd[i - 1] + dl;
S[i] = S[i - 1] + sw[i - 1] * dl;
dl = d;
}
sw[n + 1] = sw[n] + w;
sd[n + 1] = sd[n] + d;
S[n + 1] = S[n] + sw[n] * d;
n++;
for(int i = 1; i <= 2; i++) SA();
cout << best;
return 0;
}