*IX. P5896 [IOI2016]aliens

DP 优化方法大杂烩,详解 wqs 二分及其注意事项,斜率优化等其它 DP 优化方法。

**** 团队赛 T6,没想到是 IOI 原题。当时看出来要用 wqs 二分,但是我没学过(经常发生知道要用某种算法但是不会写的情况),因此最近学习了一下 wqs 二分。找题目练手的时候看到了这题,世 界 线 收 束。做题的过程中发现还要用到斜率优化,于是也学了一下。

这算是一道比较套路的题目,但套路并不意味这不是好题,毕竟我从中学到了 wqs 二分和斜率优化两种 DP 优化方法。说它套路其实也不太合适,因为 2016 年 wqs 二分还没有在 OI 界普及,甚至国外将其称之为 “Aliens’ Trick” 就是根据本题的名字而命名的,所以这个 idea 在当时应该比较新颖。


不妨对网格图的主对角线所经过的格子从左上到右下依次编号为 \(0,1,2,\cdots,m-1\)。显然,编号为 \(i\) 的格子在原网格图中的坐标为 \((i,i)\)。因为正方形的主对角线完全包含于网格图的主对角线,所以为了拍到一个点 \((r_i,c_i)\) 必然要拍到编号为 \(l_i,l_i+1,l_i+2,\cdots,r_i\) 的格子,其中 \(l_i=\min(r_i,c_i),r_i=\max(r_i,c_i)\)。因此,我们可以将题目转化为线段覆盖问题:现在有 \(n\) 条线段 \([l_i,r_i]\),我们要用最多 \(k\) 个区间 \([x_i,y_i]\) 去覆盖它们,使得每条线段至少被一个区间完全包含。即 \(\forall i,\exist j,s.t. [l_i,r_i]\in [x_j,y_j]\)。求以每个区间为对角线形成的所有正方形的面积并的最小值。接下来我们可以挖掘一些性质:

  • \(\textbf {Observation 1.}\) 如果两条线段 \(i,j\) 满足 \([l_i,r_i]\in [l_j,r_j]\),那么线段 \(i\) 对最终的答案没有影响。

    正确性显然。根据该性质,我们可以将所有线段按照左端点 \(l_i\) 从小到大为第一关键字,右端点 \(r_i\) 从大到小为第二关键字排序。然后依次遍历所有线段并记录右端点最大值 \(r\)。若当前线段 \(i\) 的右端点 \(r_i\leq r\),则忽略线段 \(i\);否则用 \(r_i\) 去更新 \(r\),即 \(r\gets r_i\)。最终所有没有被忽略的线段,一定满足左端点和右端点都单调递增。读者自证不难。

  • \(\mathbf{Observation\ 2.}\) 最终所选取的所有区间一定满足 \(x_i<x_{i+1},y_i<y_{i+1}\ (1\leq i<k)\)。

    读者自证不难。

  • \(\mathbf{Observation\ 3.}\) 设 \(F_i\) 为恰好选取 \(i\) 个区间时答案的最小值,那么 \(F_i\) 是一个下凸函数。

    读者自证不很难。感性理解一下即可,严格证明的话应该比较复杂。

有了上述性质,我们可以愉快地进行 DP 了:wqs 二分斜率 \(K\),然后设 \(f_i\) 表示覆盖第 \(i\) 条线段时的最小代价(线段按照左端点从小到大排序。根据性质 \(1\) 的结论,右端点也行,因为不影响线段之间的顺序)。显然有转移方程:

\[f_i=\min_{j=0}^{i-1}-K+\begin{cases}f_j+(y_i-x_{j+1}+1)^2-(y_j-x_{j+1}+1)^2&y_j\geq x_{j+1}\land j>0\\f_j+(y_i-x_{j+1}+1)^2&\mathrm{otherwise}\end{cases}
\]

这个分情况讨论很讨厌,尝试把它消灭掉:设 \(g_i=(y_i-x_{i+1}+1)^2[y_i\geq x_{i+1}\land i>0]\),那么转移方程变为 \(f_i=\min_{j=0}^{i-1}f_j+(y_i-x_{j+1}+1)^2-g_j-K\)。显然的斜率优化,但是我不会,所以多讲一点:拆开变成 \(f_i=\min_{j=1}^{i-1} f_j+(y_i+1)^2-2(y_i+1)x_{j+1}+x^2_{j+1}-g_j-K\)。先将所有 \(y_i\) 加上 \(1\)(不影响单调性),忽略掉 \(\min\) 再移移项,写成 \(Y=kX+b\) 的形式,\(f_j+x^2_{j+1}-g_j-K=2y_ix_{j+1}+(f_i-y_i^2)\)。那么 \(Y=f_j+x^2_{j+1}-g_j-K\),\(k=2y_i\),\(X=x_{j+1}\),\(b=f_i-y^2_i\)。将 \((X_j,Y_j)\) 看做一个点,因为 \(k\) 确定了,现在就要找使得 \(b\) 最小的 \((X_j,Y_j)\)(这样能使得 \(f_i\) 最小)。由于 \(k,X\) 都是单调递增的,所以单调队列维护下凸包即可。

具体地,记 \(k_{i,j}\) 为点 \((X_i,Y_i)\) 与 \((X_j,Y_j)\) 之间的斜率。首先将点 \(0\) 加入单调队列,接下来遍历从小到大每个位置 \(i\):

  • 若单调队列大小不小于 \(2\),设 \(a,b\) 分别为队首的第一个和第二个点,若 \(k_{a,b}\leq k=2y_i\) 则 \(b\) 一定不劣于 \(a\),弹出队首。重复该操作直到单调队列大小为 \(1\) 或 \(k_{a,b}>2y_i\)。
  • 此时队首 \(a\) 即为最优决策 \(j\),\(f_j\to f_i\) 转移并记录选择的区间个数。
  • 若单调队列大小不小于 \(2\),设 \(c,d\) 分别为队尾的倒数第二个和倒数第一个点;若 \(k_{c,d}\geq k_{d,i}\) 则 \(d\) 一定不在下凸包上,弹出队尾。重复该操作直到单调队列大小为 \(1\) 或 \(k_{c,d}<k_{d,i}\)。
  • 将点 \(i\) 加入单调队列。

我们需要求出在代价最小的前提下最少的区间个数。不妨设 \(num_i\) 为覆盖前 \(i\) 条线段且代价最小时最少的区间个数 ,那么因为 \(num_i\) 显然有单调性,所以我们每次转移时只需要选择最前面的一个决策点转移即可,即第一步操作弹出队首时,将条件 \(k_{a,b}\leq 2y_i\) 改为 \(k_{a,b}<2y_i\),这样就保证了相同优劣的决策点,前者不会被后者所弹出(第三步的条件不需要改,因为是前面的决策点弹出后面的决策点,不影响结果)

时间复杂度 \(\mathcal{O}(n\log V)\),其中 \(V\) 是二分范围,本题中为 \(m^2\)。浮点数比较建议使用 \(eps\)。代码倒是不难写。

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. #define ll long long
  4. #define ld long double
  5. const int N=1e5+5;
  6. const ld eps=1e-10;
  7. ll n,m,k,c,ans;
  8. struct seg{
  9. int l,r;
  10. bool operator < (const seg &v) const{
  11. return l!=v.l?l<v.l:r>v.r;
  12. }
  13. }p[N];
  14. ll K,f[N],g[N],num[N];
  15. ll sq(ll x){return x*x;}
  16. ll Y(int i){return f[i]+sq(p[i+1].l)-g[i]-K;}
  17. ll X(int i){return p[i+1].l;}
  18. ld slope(int i,int j){return (ld)(Y(j)-Y(i))/(X(j)-X(i));}
  19. ll hd,tl,d[N];
  20. bool check(){
  21. d[hd=tl=1]=0;
  22. for(int i=1;i<=n;i++){
  23. while(hd<tl&&slope(d[hd],d[hd+1])+eps<=2*p[i].r)hd++;
  24. int j=d[hd]; num[i]=num[j]+1,f[i]=f[j]+sq(p[i].r-p[j+1].l)-g[j]-K;
  25. if(i<n)while(hd<tl&&slope(d[tl-1],d[tl])-eps>=slope(d[tl],i))tl--;
  26. d[++tl]=i;
  27. } return num[n]<=k;
  28. }
  29. int main(){
  30. cin>>n>>m>>k;
  31. for(int i=1,c,r;i<=n;i++){
  32. cin>>p[i].l>>p[i].r;
  33. if(p[i].l>p[i].r)swap(p[i].l,p[i].r);
  34. } sort(p+1,p+n+1);
  35. for(int i=1,r=-1;i<=n;i++)if(p[i].r>r)r=p[i].r,p[++c]=p[i]; n=c;
  36. for(int i=1;i<n;i++)if(p[i].r>=p[i+1].l)g[i]=sq(p[i].r-p[i+1].l+1);
  37. for(int i=1;i<=n;i++)p[i].r++;
  38. ll l=-1e12,r=0;
  39. while(l<r)K=(l+r>>1)+1,check()?(l=K,ans=f[n]+K*k):r=K-1;
  40. cout<<ans<<endl;
  41. return 0;
  42. }

P5896 [IOI2016]aliens的更多相关文章

  1. DP 优化方法大杂烩 & 做题记录 I.

    标 * 的是推荐阅读的部分 / 做的题目. 1. 动态 DP(DDP)算法简介 动态动态规划. 以 P4719 为例讲一讲 ddp: 1.1. 树剖解法 如果没有修改操作,那么可以设计出 DP 方案 ...

  2. Uva12206 Stammering Aliens 后缀数组&&Hash

    Dr. Ellie Arroway has established contact with an extraterrestrial civilization. However, all effort ...

  3. HDU4080 Stammering Aliens(二分 + 后缀数组)

    题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=4080 Description Dr. Ellie Arroway has establish ...

  4. UVA 12206 - Stammering Aliens(后缀数组)

    UVA 12206 - Stammering Aliens 题目链接 题意:给定一个序列,求出出现次数大于m,长度最长的子串的最大下标 思路:后缀数组.搞出height数组后,利用二分去查找就可以 这 ...

  5. Stammering Aliens

    Stammering Aliens Time Limit: 2000MS   Memory Limit: 65536K       Description Dr. Ellie Arroway has ...

  6. XCOM2中敌对生物设计分析(Aliens篇)

    Aliens Aliens作为游戏设定中入侵的外星人,有各式外貌及奇特的战斗方式,掌握一些高能科技或利用精神力量进行攻击 Sectoid 使用灵能战斗的外星人,并无高级版本,初级便会使用精神控制,生命 ...

  7. UVA10570-Meeting with Aliens(枚举)

    Problem UVA1616-Caravan Robbers Accept: 531  Submit: 2490Time Limit: 3000 mSec Problem Description I ...

  8. 【UOJ#236】[IOI2016]railroad(欧拉回路,最小生成树)

    [UOJ#236][IOI2016]railroad(欧拉回路,最小生成树) 题面 UOJ 题解 把速度看成点,给定的路段看成边,那么现在就有了若干边,然后现在要补上若干边,以及一条\([inf,\) ...

  9. UVA-10570 Meeting with Aliens (枚举+贪心)

    题目大意:将一个1~n的环形排列变成升序的,最少需要几次操作?每次操作可以交换任意两个数字. 题目分析:枚举出1的位置.贪心策略:每次操作都保证至少一个数字交换到正确位置上. # include< ...

随机推荐

  1. 使用Servlet前Tomcat介绍

    虚拟目录的映射方式:让tomcat服务器自动映射tomcat服务器会自动管理webapps目录下的所有web应用,并把它映射成虚似目录.换句话说,tomcat服务器webapps目录中的web应用,外 ...

  2. zip和flatMap没有生效

    在Reactor 中flatMap和zip等没有生效 1.一个简单的示例代码如下: 2.示例运行结果 3.得到结论 最近在项目中使用了 Project Reactor ,但发现代码在写着写着有些地方没 ...

  3. 国产Linux服务器-Jexus的初步使用

    题记:年末研究了一些关于Net跨平台的东西,没错,就是Jexus,就是Windows下面的IIS. 官网:https://www.jexus.org/ 先看看官网的解释再说其他的问题,Jexus就是L ...

  4. (一)Mongodb学习之 Centos 7 单机部署

    学习参考:https://www.runoob.com/mongodb/mongodb-tutorial.html 一.部署环境 1.系统:Centos 7 2.mongodb: mongodb-li ...

  5. Linux 文本三剑客之 awk

    Linux 系统中一切皆文件. 文件是个文本.可以读.可以写,如果是二进制文件,还能执行. 在使用Linux的时候,大都是要和各式各样文件打交道.熟悉文本的读取.编辑.筛选就是linux系统管理员的必 ...

  6. Navicat15 For Mysql最新版完美破解图文教程(支持Win和Mac)

    Navicat15 For Mysql最新版完美破解 欢迎关注博主公众号[跟着Mic学架构],专注于分享Java领域技术干货,回复关键字 [面试资料] 可以获得海量面试资料. 申明,本教程 Navic ...

  7. ☕【Java技术指南】「序列化系列」深入挖掘FST快速序列化压缩内存的利器的特性和原理

    FST的概念和定义 FST序列化全称是Fast Serialization Tool,它是对Java序列化的替换实现.既然前文中提到Java序列化的两点严重不足,在FST中得到了较大的改善,FST的特 ...

  8. Mac 搭建后端PHP+Go环境

    准备工作 1. 安装brew命令 #很慢很慢.. ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/insta ...

  9. IP基础 & 子网划分 & 路由寻址

    IP地址详解 IP地址概念 就像用身份证号码来区别毎个人一样,为了区别 网上的每台计算机,我们给因特网上的每一台计算机一个唯一的编号 ,我们把它称为IP地址 IP地址就是一个唯一标识 ,是一段网络编码 ...

  10. topk算法

    方法一 堆排序 自建堆 heapMax方法,从上至下调整堆 pop时,可以使用自上而下调整堆,调用heapMax(arr,0,sz-1); push时,需要自下到上调整即 从上到下调整: void h ...