# [BZOJ4700]适者 CDQ分治

1、递归处理左右区间
2、右区间按a[]排升序，即自变量从小到大
3、左区间加入单调队列
4、两个指针扫一下，把左区间的信息加到右区间上
5、整个区间按d[]排序，即按斜率排升序（注意这里斜率取负数）

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>

#define N 300050
#define mid ((l + r) >> 1)
#define INF (1LL<<62)

using namespace std;
typedef long long LL;
struct Monster{ LL a,d,c,_; }x[N],tmp[N];
int q[N],h,t,n,ATK;
LL sum_d[N];
inline void ut(LL &x,LL y) { x = min(x,y); }
inline int rd() { int r; scanf("%d",&r); return r; }

bool cmp1(Monster p1,Monster p2) {
return p1.d * p2.a < p2.d * p1.a;
}
bool cmp2(Monster p1,Monster p2) { return p1.a < p2.a; }

void _sort1(int l,int r) {
int p1 = l , p2 = mid+1 , cur = l-1;
while (p1<mid && p2<r) {
if (x[p1].a < x[p2].a)
tmp[++cur] = x[p1] , p1++;
else
tmp[++cur] = x[p2] , p2++;
}
while (p1 <= mid) tmp[++cur] = x[p1] , p1++;
while (p2 <= r) tmp[++cur] = x[p2] , p2++;
for (int _=l;_<=r;_++) x[_] = tmp[_];
}

void _sort2(int l,int r) {
int p1 = l , p2 = mid+1 , cur = l-1;
while (p1<mid && p2<r) {
if (x[p1].d < x[p2].d)
tmp[++cur] = x[p1] , p1++;
else
tmp[++cur] = x[p2] , p2++;
}
while (p1 <= mid) tmp[++cur] = x[p1] , p1++;
while (p2 <= r) tmp[++cur] = x[p2] , p2++;
for (int _=l;_<=r;_++) x[_] = tmp[_];
}

inline LL calc(int p1,int p2) {
return x[p1].c + x[p2].c + x[p1].d * x[p2].a;
}

void solve(int l,int r) {
if (l == r) return ;
solve(l,mid); solve(mid+1,r);

_sort2(mid+1,r);

q[h=t=1] = l;
for (int i=l+1;i<=mid;i++) {
while (h<=t && x[i].c > x[ q[t] ].c) t--;
q[++t] = i;
}

for (int i=mid+1;i<=r;i++) {
while (h<t && calc(q[h],i) < calc(q[h+1],i)) h++;
x[i]._ = max( x[i]._ , calc(q[h],i) );
}

_sort1(l,r);
}
//36+42+30
int main() {
#ifndef ONLINE_JUDGE
freopen("1.in","r",stdin);
#endif
n = rd() , ATK = rd();
for (int i=1;i<=n;i++) x[i].a = rd() , x[i].d = rd() , x[i]._ = -INF;
for (int i=1;i<=n;i++) x[i].d = (int) ceil( (double)x[i].d / (double)ATK );
sort(x+1,x+n+1,cmp1);

LL cur = 0LL , sum = 0LL;
for (int i=1;i<=n;i++) sum_d[i] = sum_d[i-1] + x[i].d;
for (int i=n;i>=1;i--) {
x[i].c = x[i].d * cur + x[i].a * (sum_d[i]-1);
sum +=  x[i].d * cur + x[i].a * (x[i].d-1);
cur += x[i].a;
}

//转成斜率
for (int i=1;i<=n;i++) x[i].d = -x[i].d;
//  sort(x+1,x+n+1,cmp2);
solve(1,n);

LL ans = INF;
for (int i=1;i<=n;i++) ut(ans,sum-x[i]._);
cout << ans << endl;
return 0;
}