传送门
题解:
容易想到首先要求一个LIS。
根据以其结尾的LIS长度,把点分为若干集合,设为 ,容易注意到一个集合中横座标增加的同时纵座标减小。
容易得到一个显然的DP:
发现权值的图像好像是反比例函数,考虑什么时候决策 比决策 优秀。
发现决策的分界线是一条斜率为正的直线,一个半平面会选择 另一个会选择 。
但是我们显然是不能把所有半平面算出来求半平面交的。
但是我们知道如果对于某个点决策 比决策 优秀,则这个点左边/右边的所有点决策 都比决策 优秀。
于是可以分治下去找到最优决策,注意DP对座标有要求,结合线段树进行分治即可。
分治套分治,复杂度两个log。
代码:
#include<bits/stdc++.h>
#define ll long long
#define re register
#define cs const
namespace IO{
inline char gc(){
static cs int Rlen=1<<22|1;static char buf[Rlen],*p1,*p2;
return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1++;
}template<typename T>T get_integer(){
char c;bool f=false;while(!isdigit(c=gc()))f=c=='-';T x=c^48;
while(isdigit(c=gc()))x=((x+(x<<2))<<1)+(c^48);return f?-x:x;
}inline int gi(){return get_integer<int>();}
}using namespace IO;
using std::cerr;
using std::cout;
cs int N=2e5+7;
int n,T;
int x[N],y[N],id[N];
int lis[N],a[N],mx;
ll calc(int i,int j){
return (ll)(x[i]-x[j])*(y[i]-y[j]);
}
std::vector<int> ps[N];
ll dp[N];
namespace SGT{
std::vector<int> sol[N<<2];
#define lc u<<1
#define rc lc|1
void DP(int ql,int qr,cs std::vector<int> &q,int l,int r,cs std::vector<int> &ps){
int qm=(ql+qr)>>1,qid=q[qm],m=0;ll tmp=1e18;
for(int re i=l;i<=r;++i)
if(tmp>dp[ps[i]]+calc(ps[i],qid))
{tmp=dp[ps[i]]+calc(ps[i],qid),m=i;}
dp[qid]=std::min(dp[qid],tmp);
if(ql<qm)DP(ql,qm-1,q,m,r,ps);
if(qm<qr)DP(qm+1,qr,q,l,m,ps);
}
void ins(int u,int l,int r,int p,cs std::vector<int> &ps){
if(y[ps[l]]<y[p]&&x[ps[r]]<x[p])
return sol[u].push_back(p);
if(y[ps[r]]>y[p]||x[ps[l]]>x[p])
return ;int m=(l+r)>>1;
ins(lc,l,m,p,ps);ins(rc,m+1,r,p,ps);
}
void solve(int u,int l,int r,cs std::vector<int> &ps){
if(sol[u].size())DP(0,sol[u].size()-1,sol[u],l,r,ps);
sol[u].clear();if(l==r)return ;int m=(l+r)>>1;
solve(lc,l,m,ps);solve(rc,m+1,r,ps);
}
}
void Main(){
n=gi(),T=gi();
for(int re i=1;i<=n;++i)
x[i]=gi(),y[i]=gi(),id[i]=i;
std::sort(id+1,id+n+1,
[](int i,int j){return x[i]<x[j];});mx=0;
for(int re i=1;i<=n;++i){
int j=id[i];
if(y[j]>=a[mx]){
lis[j]=++mx;
a[mx]=y[j];
}else {
lis[j]=std::upper_bound(a+1,a+mx+1,y[j])-a;
a[lis[j]]=y[j];
}ps[lis[j]].push_back(j);
}std::fill(dp+1,dp+n+1,1e18);
for(int i:ps[1])dp[i]=(ll)x[i]*y[i];
for(int re i=2;i<=mx;++i){
for(int j:ps[i])
SGT::ins(1,0,ps[i-1].size()-1,j,ps[i-1]);
SGT::solve(1,0,ps[i-1].size()-1,ps[i-1]);
}ll ans=1e18;
for(int i:ps[mx])
ans=std::min(ans,dp[i]+(ll)(T-x[i])*(T-y[i]));
cout<<ans<<"\n";
}
inline void file(){
#ifdef zxyoi
freopen("mischief.in","r",stdin);
#endif
}signed main(){file();Main();return 0;}