首先求出
l
i
s
lis
lis
然后对于
l
i
s
i
lis_i
lisi按照值分层转移
显然每一层的点是从左上到右下这样单调的
对于相邻两层的转移
可以列出
D
P
DP
DP式子
f
i
=
min
j
,
x
j
<
x
i
,
y
j
<
y
i
(
f
j
+
(
x
i
−
x
j
)
∗
(
y
i
−
y
j
)
)
f_i=\min_{j,x_j<x_i,y_j<y_i}(f_j+(x_i-x_j)*(y_i-y_j))
fi=minj,xj<xi,yj<yi(fj+(xi−xj)∗(yi−yj))
冷静一下发现没法直接斜率优化
首先不考虑
i
→
j
i\rightarrow j
i→j要满足
x
i
<
x
j
,
y
i
<
y
j
x_i<x_j,y_i<y_j
xi<xj,yi<yj的限制
考虑如果
i
,
j
(
i
<
j
)
i,j(i<j)
i,j(i<j)转移到
k
k
k
若
j
j
j比
i
i
i优
有
f
j
+
(
x
k
−
x
j
)
(
y
k
−
y
j
)
<
f
i
+
(
x
k
−
x
i
)
(
y
k
−
y
i
)
f_j+(x_k-x_j)(y_k-y_j)<f_i+(x_k-x_i)(y_k-y_i)
fj+(xk−xj)(yk−yj)<fi+(xk−xi)(yk−yi)
x
k
(
y
i
−
y
j
)
+
y
k
(
x
i
−
x
j
)
≤
(
f
i
+
x
i
y
i
)
−
(
f
j
+
x
j
y
j
)
x_k(y_i-y_j)+y_k(x_i-x_j)\le(f_i+x_iy_i)-(f_j+x_jy_j)
xk(yi−yj)+yk(xi−xj)≤(fi+xiyi)−(fj+xjyj)
由于
i
,
j
i,j
i,j同一层是单调的,所以
y
i
−
y
j
,
x
i
−
x
j
y_i-y_j,x_i-x_j
yi−yj,xi−xj一定一正一负
对于
i
,
j
i,j
i,j看做常量的话就是对于
k
(
x
k
,
y
k
)
k(x_k,y_k)
k(xk,yk)就是一个斜率为正的直线的一侧
由于
k
k
k也是单调的
所以转移具有决策单调性
不过注意如果按照
x
x
x有序的话决策单调性是反的
即
i
,
j
i,j
i,j越大,可以转移的
k
k
k为越小的一段
于是分治优化即可
现在考虑
x
,
y
x,y
x,y大小的限制
可以分治优化
由于每一层点单调
所以分治可以做到一个
l
o
g
log
log
复杂度 O ( n l o g 2 n ) O(nlog^2n) O(nlog2n)
#include<bits/stdc++.h>
using namespace std;
#define cs const
#define int long long
#define re register
#define pb push_back
#define pii pair<int,int>
#define ll long long
#define y1 shinkle
#define fi first
#define se second
#define bg begin
cs int RLEN=1<<20|1;
inline char gc(){
static char ibuf[RLEN],*ib,*ob;
(ib==ob)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
return (ib==ob)?EOF:*ib++;
}
inline int read(){
char ch=gc();
int res=0;bool f=1;
while(!isdigit(ch))f^=ch=='-',ch=gc();
while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
return f?res:-res;
}
inline ll readll(){
char ch=gc();
ll res=0;bool f=1;
while(!isdigit(ch))f^=ch=='-',ch=gc();
while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
return f?res:-res;
}
inline int readstring(char *s){
int top=0;char ch=gc();
while(isspace(ch))ch=gc();
while(!isspace(ch)&&ch!=EOF)s[++top]=ch,ch=gc();
return top;
}
template<typename tp>inline void chemx(tp &a,tp b){a<b?a=b:0;}
template<typename tp>inline void chemn(tp &a,tp b){a>b?a=b:0;}
cs int N=200005,M=1000005;
int n,lm,ln;
namespace bit{
int tr[M];
#define lb(x) (x&(-x))
inline void update(int p,int k){
for(;p<=lm;p+=lb(p))chemx(tr[p],k);
}
inline int query(int p,int res=0){
for(;p>0;p-=lb(p))chemx(res,tr[p]);return res;
}
}
pii p[N];
inline ll dis(pii x,pii y){
return abs((ll)(x.fi-y.fi)*(x.se-y.se));
}
int ls[N];
ll f[N];
vector<int> pt[N],z;
namespace Seg{
vector<int> q[N<<2],tp;
#define lc (u<<1)
#define rc ((u<<1)|1)
#define mid ((l+r)>>1)
void update(int u,int l,int r,int k){
// cout<<z[l]<<" "<<z[r]<<" "<<k<<" "<<p[k].se<<" "<<p[z[l]].se<<" "<<p[k].fi<<" "<<p[z[r]].fi<<'\n';
if(p[k].se>=p[z[l]].se&&p[k].fi>=p[z[r]].fi){
// cout<<l<<" "<<r<<" "<<k<<'\n';
q[u].pb(k);return;
}
if(p[k].se<=p[z[r]].se||p[k].fi<=p[z[l]].fi)return;
update(lc,l,mid,k),update(rc,mid+1,r,k);
}
void solve(int l,int r,int ql,int qr){
ll res=1e18;int ps=0,id=tp[mid];
for(int i=ql;i<=qr;i++){
ll now=f[z[i]]+dis(p[z[i]],p[id]);
if(now<res)res=now,ps=i;
}
chemn(f[id],res);
if(l<mid)solve(l,mid-1,ps,qr);
if(mid<r)solve(mid+1,r,ql,ps);
}
void query(int u,int l,int r){
if(q[u].size()){
tp=q[u];
solve(0,q[u].size()-1,l,r);
q[u].clear();
}
if(l==r)return;
query(lc,l,mid),query(rc,mid+1,r);
}
#undef lc
#undef rc
#undef mid
}
inline void trans(cs vector<int> &pre,cs vector<int> &now){
z=pre;
int l=(int)pre.size()-1;
for(int x:now){
Seg::update(1,0,l,x);
}
Seg::query(1,0,l);
}
signed main(){
#ifdef Stargazer
freopen("lx.in","r",stdin);
#endif
n=read(),lm=read();
for(int i=1;i<=n;i++)p[i].fi=read(),p[i].se=read();
sort(p+1,p+n+1);
for(int i=1;i<=n;i++){
ls[i]=bit::query(p[i].se)+1;
chemx(ln,ls[i]);
bit::update(p[i].se,ls[i]);
pt[ls[i]].pb(i);
// cout<<i<<" "<<ls[i]<<'\n';
}
memset(f,127/3,sizeof(f));
for(int &i:pt[1])f[i]=dis(p[i],pii(0,0));
//,cout<<i<<" "<<f[i]<<'\n';
for(int i=2;i<=ln;i++)
trans(pt[i-1],pt[i]);
ll res=1e18;
for(int &i:pt[ln])chemn(res,f[i]+dis(p[i],pii(lm,lm)));
cout<<res<<'\n';
}