码迷,mamicode.com
首页 > Windows程序 > 详细

6319. 【省选组】【USACO 2019 February Platinum】Problem 3. Mowing Mischief

时间:2020-05-10 10:42:02      阅读:91      评论:0      收藏:0      [点我收藏+]

标签:str   就是   子序列   包含   如何   http   lin   答案   show   

题目

有一个坐标范围为\((0..T,0..T)\)的网格图,
给你\(n\)个整点,你要在其中尽量多的点(左下角和右上角必须选),使得它们互为二维偏序。
在这个基础上,最小化相邻的二维偏序点之间一个左下角一个右上角形成的矩形的面积和。
\(n\leq 2e5\)
\(T\leq 1e6\)
保证横坐标、纵坐标互不相同。


思考历程

有个小插曲:我很久之后才发现要先保证点的数量尽量多。
将每个点以横坐标为第一关键字,以纵坐标为第二关键字,排序。
“尽量多”显然就是找最长上升子序列。
\(f_i\)表示以第\(i\)个点结尾的最长上升子序列长度,随便预处理出来。
\(g_i\)表示以第\(i\)个结尾的最小答案。
转移的时候,为了保证选的点集是个最长上升子序列,在转移的条件中多加一条限制:\(g_j\)转移到\(g_i\)时,必须要满足\(f_j+1=f_i\)(当然之前二维偏序的限制也要保证)
于是简单的\(O(n^2)\)做法就出炉了。

接下来还有些想法,但是有些漏洞,就不讲了。


正解

考虑将\(f_i=k\)的点丢到集合\(S_k\)。将\(S_k\)中的点按照\(x\)坐标排序。
可以发现,\(S_k\)中的点一定是随着\(x\)递增,\(y\)递减的(即全是逆序对)。
证明:如果出现了二维偏序,于是右上方的那个点可以被更新。

对于点\(i\)而言,\(S_{f_i-1}\)中能够转移到它的点形成一个区间。

转移时新增的贡献为\((x_i-x_j)(y_i-y_j)\),拆开,除去只跟\(i\)或者只跟\(j\)有关的项,于是变成了找\(w_j-x_iy_j-x_jy_i\)最小,其中\(w_j\)是只跟\(j\)有关的值。
接下来可以证明一个性质:
对于\(S_k\)中的某个点\(i\)\(j\),满足\(i<j\),若有\(p,q\in S_{k-1}\)\(p<q\)\(p,q\)都能转移到\(i,j\)
如果对于\(i\)而言,\(p\)\(q\)优,则对于\(j\)而言,\(p\)仍然比\(q\)优。
证明:
对于\(i\)而言\(p\)\(q\)优,即\(w_p-x_iy_p-y_ix_p<w_q-x_iy_q-y_ix_q\)
\((w_p-w_q)-x_i(y_p-y_q)-y_i(x_p-x_q)<0\)
\(y_p-y_q>0,x_p-x_q<0\)得:
\(i\)增大到\(j\)时,\(x_i\)增加,\(y_i\)减少,不等式左边的后面两项都减少,于是\(p\)仍然比\(q\)优。
根据决策单调性转移:
先考虑一个特殊情况,假设\(S_{k-1}\)中每个点都可以转移到\(S_k\)中每个点。
维护一个队列,前面的比后面的大,并且前面的比后面的优。在指针从后往前扫的时候,维护队列中两两之间优劣关系的变化,如果一个元素比下一个元素劣,就把它删掉。

我的做法是这样:对于队列中相邻两个元素,在它们拼接上来的那一刻通过二分计算它们优劣关系改变的时间;然后将这些时间都丢进一个堆(或set)里面,指针移动的时候维护。
古爷说:队列中间的大小关系不会改变。这是一个1d1d的板子,它和斜率优化的区别是不能直接算出优劣关系改变的时间,所以需要二分。
我:中间的关系不会变的话,那直接扫过去,只判断队头啊。
古爷:你试试(
我:。。。
总之古爷太强了,比不过比不过。

但是有个问题是对于每个\(i\),能转移到它的点集不一定相同。
就是说可能在算\(j\)的时候,之前对于\(i\)来说,最优的\(p\)不能转移到\(j\)

古爷的做法:直接暴力线段树分治……
将每个\(p\)能覆盖的\(i\)的区间挂在线段树上,这样在线段树上每个节点的区间上,每个连向它的\(p\)都能转移到整个区间。

题解的做法很巧妙:
\(S_k\)分成若干块,满足对于每个\(p\in S_{k-1}\),它必定跟其中两个块相交(其实题解的说法似乎不是很准确,应该说,每个\(p\)覆盖的区间中有且仅有一个分界点,包括边界)
于是对于某个块来说,\(p\)覆盖的区间是一段前缀或者是一段后缀。前缀和后缀分开处理,对于每个块,连向它的\(p\)所能覆盖的区间的起点相同。用个单调队列扫一遍就可以算出答案。

当然我并没有完全看懂题解。因为它还有个二分找区间什么鬼的,不知道在讲啥。
考虑如何分块:将所有\(p\)能转移到的区间列出来,可以发现随着\(p\)递增,区间的左右端点都在递增。
将第一个区间的右端点作为分界点,然后将包含这个分界点的区间去掉,继续做下去。
这个贪心感觉是对的。
于是总的时间复杂度\(O(n\lg n)\)

代码没写。


总结

决策单调性,这个东西好像好久没有玩过了。
该好好补一下。
话说我还记得四边形不等式么……

6319. 【省选组】【USACO 2019 February Platinum】Problem 3. Mowing Mischief

标签:str   就是   子序列   包含   如何   http   lin   答案   show   

原文地址:https://www.cnblogs.com/jz-597/p/12862306.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!