传送门:点击打开链接

题意:要覆盖完n个点,要覆盖掉[i,j]的代价是(X[i]-X[j])*(X[i]-X[j])+W,求覆盖完所有点的最小代价

思路:这是一道非常裸的斜率优化。

网上讲解斜率优化的博客还是比较多的,斜率优化通常就是化简后,最后得到了一个斜率的式子

推荐个学习的链接

点击打开链接

我稍微讲下对于单调队列,我一开始看着比较费劲的地方。。

(下面内容均建立在已经读完上面那个链接的基础之上。。

用g[i,j]表示点i,j的斜率。假如之前已经有点k,j。现在考虑把i点放进去

如果有g[j,i]<g[k,j],那么j一定不是最优的,现在我们来证明:

下面这张图是j需要被删除的情况。

如果g[j,i]<sum[i],那么根据之前我们列出的不等式的含义,可以知道i比j更优。

如果g[j,i]>=sum[i],那么就有g[k,j]>g[j,i]>=sum[i],根据定义,如果g[k,j]<sum[i],则j最优,反之,现在是>=sum[i],所以k点最优

所以我们能够发现,无论怎样,这种情况下的J都需要删掉。

综上所述,我们就知道,我们需要维护一个斜率越来越大的点的集合,如下图

我们接下来说一下,队列需要如何来维护。

下面的sum是针对上面那个地址来的,其实对应了本道题目的第i个位置

我们用单调队列来维护上面这个图。

删除队首没用的点:

取队首第一个点和第二个点,计算斜率,记为k

如果k<=sum,说明第二个点更优。所以我们就把队首那个点删掉,直到k>sum或者队列为空

由于随着i往后,sum会越来越大。我们可以发现,sum增大以后,我们刚刚删掉的点也不可能是最优的

所以就证明了我们删除队首的一些点的正确性。

新添加点:从队尾加入点,先看i与队列最后一个点的斜率记为a,队列最后一个点和最后第二个点的斜率记为b。

如果a<=b,那么就把最后一个点删掉,直到a>b或者队列中没有点。

为了减少我们思考复杂度,我们可以写好3个函数,geup(),getdown(),getdp(),之后的程序就很容易写了

PS:我们仔细再看下上面这道题为什么能用单调队列。

因为sum会越来越大,说白了就是你把斜率不等式写出来,当符号是<时候,右边是单调递增。当符号是>时候,右边是单调递减

只有这种情况,才可以使用单调队列来斜率优化。

如果sum不是单调的,那么就必须写凸包,然后再在凸包上三分答案。

#include <map>
#include <set>
#include <cmath>
#include <ctime>
#include <stack>
#include <queue>
#include <cstdio>
#include <cctype>
#include <bitset>
#include <string>
#include <vector>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
#define fuck(x) cout<<"["<<x<<"]";
#define FIN freopen("input.txt","r",stdin);
#define FOUT freopen("output.txt","w+",stdout);
//#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const int MX = 2e5 + 5;LL A[MX], dp[MX], w;
int Q[MX], c, r;
LL getup(int i, int j) {return dp[j - 1] + A[j] * A[j] - (dp[i - 1] + A[i] * A[i]);
}
LL getdown(int i, int j) {return A[j] - A[i];
}
LL getdp(int i, int j) {return dp[j - 1] + (A[i] - A[j]) * (A[i] - A[j]) + w;
}
int main() {int T; //FIN;scanf("%d", &T);while(T--) {int n;c = 1; r = 0;scanf("%d%lld", &n, &w);for(int i = 1; i <= n; i++) {scanf("%lld", &A[i]);}sort(A + 1, A + 1 + n);for(int i = 1; i <= n; i++) {while(r - c + 1 >= 2 && getup(Q[c], Q[c + 1]) <= 2 * A[i]*getdown(Q[c], Q[c + 1])) c++;dp[i] = min(getdp(i, Q[c]), dp[i - 1] + w);while(r - c + 1 >= 2 && getup(Q[r], i)*getdown(Q[r - 1], Q[r]) <= getdown(Q[r], i)*getup(Q[r - 1], Q[r])) r--;Q[++r] = i;}printf("%lld\n", dp[n]);}return 0;
}

这里还介绍一种类似整体二分的思想的分治的方法,可以用来替代单调队列

不过单调队列总的复杂度是O(n),分治的方法总的复杂度是O(nlogn)

虽然变慢了一个log,但是代码编写上简单非常多。

void dfs(int l, int r, int dl, int dr) {//[l,r]表示现在更新[l,r]区间dp[i]的最优值//用j -> f(i),表示j是更新f(i)最优值的最优点//那么[dl,dr]表示更新dp([l,r])的点,一定在[dl,dr]范围内int mid = (l + r) >> 1; int dm = dl;int g = inf;for (int i = dl; i <= dr; i++) {if(g < dp[i] + f(i, mid)) {g = dp[i] + f(i, mid);//记录更新dp[mid]的最优dm = i;//记录更新dp[mid]的最优点}}dp[mid] = g; //更新dp[mid]的值//因为上文叙述的单调性,//更新[l,mid-1]的最优点,一定在[dl,dm]范围内if(l < mid) dfs(l, mid - 1, dl, dm);//更新[mid+1,r]的最优点,一定在[dm,dr]范围内if(mid < r) dfs(mid + 1, r, dm, dr);//此份代码dfs顺序有点问题,并不正确,但是并不影响理解
}

斜率优化 Snowdrop修长廊 scu dp练习B题相关推荐

  1. B: Snowdrop修长廊

    Snowdrop修长廊 描述 Snowdrop现在是世界著名的工程师.因为重庆的天气太热了, Snowdrop决定修一条长廊,并且长廊要覆盖必须覆盖的n个点.为 了简化整个问题,我们把一条路抽象成一维 ...

  2. [SCU 4509] Snowdrop修长廊 (斜率DP)

    SCU - 4509 使用若干条线段,覆盖坐标轴上的 N个点 覆盖 [i,j][i, j]的代价为cost(i,j)=W+(xi−xj)2cost(i,j) = W + (x_i-x_j)^2 求覆盖 ...

  3. 『摆渡车 斜率优化dp及总结』

    摆渡车的题解我已经写过一遍了,在这里,这次主要从斜率优化的角度讲一下摆渡车,并总结一下斜率优化会出现的一些奇奇怪怪的错误. 摆渡车 Description 有 n 名同学要乘坐摆渡车从人大附中前往人民 ...

  4. BZOJ 1597: [Usaco2008 Mar]土地购买( dp + 斜率优化 )

    既然每块都要买, 那么一块土地被另一块包含就可以不考虑. 先按长排序, 去掉不考虑的土地, 剩下的土地长x递增, 宽y递减 dp(v) = min{ dp(p)+xv*yp+1 } 假设dp(v)由i ...

  5. BZOJ 1492: [NOI2007]货币兑换Cash [CDQ分治 斜率优化DP]

    传送门 题意:不想写... 扔链接就跑 好吧我回来了 首先发现每次兑换一定是全部兑换,因为你兑换说明有利可图,是为了后面的某一天两种卷的汇率差别明显而兑换 那么一定拿全利啊,一定比多天的组合好 $f[ ...

  6. 『玩具装箱TOY 斜率优化DP』

    玩具装箱TOY(HNOI2008) Description P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京.他使用自己的压缩器进行压缩,其可以将任意物品变成一堆,再放到一种特殊 ...

  7. NOI2007 货币兑换 - CDQ分治斜率优化dp

    斜率优化dp维护一个凸壳.如果\(x, y\)坐标都递增,可以用单调队列,如果只有\(x\)递增,可以在凸壳上二分斜率,如果\(x, y\)都不递增,则需要在凸包中插入,可以用平衡树或cdq分治维护. ...

  8. CF-311B Cats Transport(斜率优化DP)

    题目链接 题目描述 小S是农场主,他养了 \(M\)只猫,雇了 \(P\) 位饲养员. 农场中有一条笔直的路,路边有 \(N\) 座山,从 \(1\) 到 \(N\)编号. 第 \(i\) 座山与第 ...

  9. 【洛谷3648】[APIO2014] 序列分割(斜率优化DP)

    点此看题面 大致题意: 你可以对一个序列进行\(k\)次分割,每次得分为两个块元素和的乘积,求总得分的最大值. 区间\(DPor\)斜率优化\(DP\) 这题目第一眼看上去感觉很明显是区间\(DP\) ...

最新文章

  1. druid+spring配置
  2. python matplot 绘图
  3. YYDispatchQueuePool 学习笔记
  4. @getmapping注解的作用_一口气说出6种,@Transactional注解的失效场景
  5. Imation亏损额急剧增长 CEO仍表示“成功”
  6. 微软CEO纳德拉开讲,2016微软开发者峰会在京召开
  7. Binary XML file line #2: You must supply a layout_height attribute inflate
  8. python做地图导航_「Python」利用高德地图做你想做之事
  9. c语言自由存储区,C/C++ 内存分区以及自由存储区和堆的区别
  10. java实现人脸识别源码【含测试效果图】——前期准备工作及访问提示
  11. acr122ua9读写软件_NFC读卡器ACR122U-A9 非接触型IC读写器 龙杰读卡器 IC解密器
  12. steam怎么设公用计算机,steam家庭共享是什么?steam设置家庭共享的方法
  13. 《Nodejs开发加密货币》之十六:利益,魔鬼与天使的共同目标
  14. numpy中的linspace函数
  15. 最新BBS上的变态网名大全
  16. windows下GMT绘制矢量图
  17. mysql获取汉字首字母拼音,包括复杂字
  18. 一大堆模块的结晶……
  19. 1990-1999年最强华语金曲TOP100
  20. 安装MongoDB出现 service MongoDB failed to start,verify that you have sufficient privileges to start

热门文章

  1. Android Studio形成扫码二维码的代码
  2. 计算机网络之【物理层】
  3. 华为学习小米做智能电视能成功么?
  4. 衡量二分类模型的统计指标(TN,TP,FN,FP,F1,准确,精确,召回,ROC,AUC)
  5. LeetCode经典300题【C++版】
  6. JS 文件流和base64互转
  7. 每周算法题(从三个红球、五个白球、六个黑球中任意取出八个球,且其中必须有白球,输出所有可能的方案,有1、2、3、4数字,组成无重复的三位数两个乒乓球队进行比赛,各出三人。甲队为a,b,c)
  8. SQL注入 Less23(过滤注释符)
  9. selenium【自动下载谷歌驱动】自动获取谷歌版本,并自动下载对应版本的chromedriver.exe
  10. LLM大模型中文开源数据集集锦(三)