线段树+决策单调性-好题-[USACO19FEB]Mowing Mischief-解题报告
好题!我把minmax看反推了半天 Blog
我们肯定要求出以每个点结尾的LIS长度,然后长度相差1的点之间转移。
性质:LIS相同的点,横坐标增加,纵坐标减小
我们列出转移方程:
看着比较像斜率优化,但是好像化简不到标准形式?这是就要用到优化DP的另一个利器了:决策单调性!
考虑
注意到
这道题的决策单调性是反的:后边的点更可能成为前边的点的最优决策点。
然后考虑如何解决
注意到,如果我们把点按照横坐标递增编号,那么同一层中,满足
复杂度
#define N 200005
int n;
struct Node
{
int x,y;
Node() {}
Node(const int _x,const int _y) {x=_x,y=_y;}
friend bool operator<(const Node &a,const Node &b) {return a.x<b.x;}
} pt[N];
il LL dis(const int a,const int b) {return abs((LL)(pt[a].x-pt[b].x)*(pt[a].y-pt[b].y));}
const LL inf=1ll<<60;
LL dp[N];
void solve(int l,int r,int al,int ar,const vector<int> &q,const vector<int> &g)
{
int _mid=(l+r)>>1,mid=q[_mid],am=0; LL t=inf;
for(ri i=al; i<=ar; ++i) if(ckmin(t,dp[g[i]]+dis(g[i],mid))) am=i;
ckmin(dp[mid],t);
if(l<_mid) solve(l,_mid-1,am,ar,q,g);
if(_mid<r) solve(_mid+1,r,al,am,q,g);
}
#define M N*4
#define ls (x<<1)
#define rs (x<<1|1)
const int rt=1;
vector<int>qu[M];
void upd(int x,int l,int r,int p,const vector<int> &g)
{
if(pt[g[l]].y<=pt[p].y&&g[r]<=p) return qu[x].pb(p);
if(pt[g[r]].y>pt[p].y||g[l]>p) return;
gm;
upd(ls,l,mid,p,g),upd(rs,mid+1,r,p,g);
}
void work(int x,int l,int r,const vector<int> &g)
{
if(Size(qu[x]))
{
solve(0,Size(qu[x])-1,l,r,qu[x],g);
qu[x].clear();
}
if(l==r) return;
gm;
work(ls,l,mid,g),work(rs,mid+1,r,g);
}
vector<int>pos[N];
int T;
int tre[N];
void upd(int x,int k)
{
for(; x<=n; x+=x&-x) ckmax(tre[x],k);
}
int ask(int x)
{
int res=0;
for(; x; x-=x&-x) ckmax(res,tre[x]);
return res;
}
int lis[N];
int ui[N],cu;
signed main()
{
#ifdef M207
freopen("in.in","r",stdin);
// freopen("ot.out","w",stdout);
#endif
in(n,T);
for(ri i=1; i<=n; ++i) in(pt[i].x,pt[i].y),ui[i]=pt[i].y;
sort(ui+1,ui+1+n);
sort(pt+1,pt+1+n);
int mx=0;
for(ri i=1,L; i<=n; ++i)
{
L=lower_bound(ui+1,ui+1+n,pt[i].y)-ui;
lis[i]=ask(L)+1,ckmax(mx,lis[i]);
upd(L,lis[i]);
pos[lis[i]].pb(i);
}
for(ri i=1; i<=n; ++i) dp[i]=inf;
for(solid i:pos[1]) dp[i]=(LL)pt[i].x*pt[i].y;
for(ri i=2; i<=mx; ++i)
{
for(solid j:pos[i]) upd(rt,0,Size(pos[i-1])-1,j,pos[i-1]);
work(rt,0,Size(pos[i-1])-1,pos[i-1]);
}
LL ans=inf;
for(solid i:pos[mx]) ckmin(ans,dp[i]+(LL)(T-pt[i].x)*(T-pt[i].y));
out(ans);
return 0;
}