P2900 [USACO08MAR] Land Acquisition G 题解
不明白为啥没人写李超线段树。
斜率优化的题通常李超也能做,这题
状态转移方程是咋来的请看别的题解。
其中
那么我们设
所以我们就用李超维护这些直线,求最小值就很简单了。
时间复杂度是
#include<bits/stdc++.h>
#define LL long long
#define LF double
#define pLL pair<LL,LL>
#define pb push_back
//#define Fi first
//#define Se second
#define Ls(x) (x<<1)
#define Rs(x) (x<<1|1)
//#define Ls(x) t[x].Lson
//#define Rs(x) t[x].Rson
using namespace std;
const LL Inf=1e18;
const LL N=1e6+5;
const LL M=1e6;
//const LL Mod;
//const LF eps;
//const LL P;
struct Nd
{
LL H,W;
}A[N],B[N];
LL n,tot,F[N];
struct Line
{
LL k,b;
}L[N];
LL Cal(LL i,LL x)
{
return L[i].k*x+L[i].b;
}
bool Pd(LL i,LL j,LL x)
{
return Cal(i,x)<Cal(j,x);
}
LL Mn[N<<2];
void Upd(LL rt,LL l,LL r,LL x)
{
if(l==r)
{
if(Pd(x,Mn[rt],l))Mn[rt]=x;
return;
}
LL mid=l+r>>1;
if(Pd(x,Mn[rt],mid))swap(x,Mn[rt]);
if(Pd(x,Mn[rt],l))Upd(Ls(rt),l,mid,x);
if(Pd(x,Mn[rt],r))Upd(Rs(rt),mid+1,r,x);
}
LL Qry(LL rt,LL l,LL r,LL x)
{
LL t=Cal(Mn[rt],x);
if(l==r)return t;
LL mid=l+r>>1;
if(x<=mid)return min(t,Qry(Ls(rt),l,mid,x));
return min(t,Qry(Rs(rt),mid+1,r,x));
}
void Ins(LL x)
{
L[x]={B[x+1].W,F[x]};
Upd(1,1,M,x);
}
int main()
{
scanf("%lld",&n);
for(int i=1;i<=n;i++)
{
scanf("%lld%lld",&A[i].H,&A[i].W);
}
sort(A+1,A+n+1,[](Nd x,Nd y)
{
if(x.H!=y.H)return x.H<y.H;
return x.W<y.W;
});
for(int i=n;i>=1;i--)
{
if(A[i].W>=B[tot].W)B[++tot]=A[i];
}
n=tot;
sort(B+1,B+n+1,[](Nd x,Nd y)
{
if(x.H!=y.H)return x.H<y.H;
return x.W<y.W;
});
L[0]={0,Inf};
L[n+1]={B[1].W,0};
Upd(1,1,M,n+1);
F[1]=B[1].W*B[1].H;
Ins(1);
for(int i=2;i<=n;i++)
{
F[i]=Qry(1,1,M,B[i].H);
// cout<<B[i].H<<' '<<B[i].W<<' '<<F[i]<<endl;
Ins(i);
}
printf("%lld\n",F[n]);
return 0;
}
//RP++