首页 > 其他分享 >斜率优化

斜率优化

时间:2024-01-29 23:22:23浏览次数:27  
标签:2r int len 斜率 MaxN tot 优化

斜率优化

前置芝士:\(斜率 = \frac{a_y-b_y}{a_x-b_x}\)

列题:P3195 [HNOI2008] 玩具装箱

首先你要知道这是 \(dp\)。

其次你要写出暴力来,这里简略一下,设 \(q_i\) 为前缀和:\(f_i = min(f_j + (q_i - q_j + i - j - 1 - l)^2)\)。
正片开始:

首先,我们发现 \(dp\) 式太复杂了,所以化简一下,因为 \(i\) 和 \(l\) 属于暂时常数,所以将其分离出来,可设 \(x_i=q_i+i,r_i=x_i-l-1\),则

\(原式 = f_j+(r_i-x_j)^2\),

将括号分解:

\(= f_j+{r_i}^2+{x_j}^2-2r_ix_j\)

再将 \(i\) 分离(单单与 \(i\) 有关的,这里消掉了,但是最终要加上!):

\(f_j+{x_j}^2-2r_ix_j\)

这里出来了单独式和系数式,可以在将两种分离开来,设 \(y_i=f_i+{x_i}^2\):

\(y_j-2r_ix_j\)

这里化不下去了,所以可设两个决策点 \(a, b\),设 \(a\) 比 \(b\) 更优,有:

\(y_a-2r_ix_a < y_b-2r_ix_b\)

\(y_a-y_b < 2r_i(x_b-x_a)\)

\(y_a-y_b > 2r_i(x_a-y_b)\)

因为我们并不关心 \(x_a\) 和 \(y_b\) 之间的关系,所以不管了:

\(\frac{y_a-y_b}{x_a-x_b} > 2r_i\)

此时我们发现,\(\frac{y_a-y_b}{x_a-x_b}\) 是个斜率式,所以可以建系,此时有:如果斜率大于 \(2r_i\),则 \(a\) 的比 \(b\) 的更优。

考虑如何用斜率来优化,很明显,当我们把一个个点维护出来后,会有一个由斜率连成的线,此时会有凸壳:

通过此图,我们可以得知:此时 \(j2\) 永远也不可能是最优的,因为如果 \(j2\) 是最优的,那么 \(2r_i\) 必然是小于 \(j2\) 和 \(j3\) 的斜率,那么 \(2r_i\) 就会小于 \(j1\) 到 \(j2\) 的斜率(一个上凸,斜率自然大一些),所以 \(j1\) 比 \(j2\) 优,所以 \(j2\) 永远不是最优的。那么对于这些完全不可能是最优的点,我们就没有必要在维护了,那么我们可以用个栈维护,因为新加的点只会对最近的几个点有影响,所以用栈即可满足。

可是维护了这样一个凸壳有什么用呢?

当我们考虑到了 \(i\),就必然有一个 \(2r_i\)(似乎是废话),先说结论:用斜率为 \(2r_i\) 的直线去切我们维护的凸壳,第一个切到的点,就是最优决策点。

为什么是这样呢?(以上为图示,可以结合食用)我们可以思考这个点(待会被称为当前点),在它往前走(也就是上面的那个)的点的斜率比 \(2r_i\) 大,所以当前点是优的,在它往后走(也就是下面的那个)的点的斜率比 \(2r_i\) 小,所以当前点更优,所以是最优决策点。

由图可知,其实切上去,就是找到第一个上面斜率大于 \(2r_i\) 的点,二分即可。

最后提醒一句,这道题很,所以这么做就行了,因为我们的 \(x_i\) 永远在递增,可是像 [NOI2007] 货币兑换 这种不递增的,就得用 \(CDQ\) 了!

code

#include <algorithm>
#include <iostream>
#define int long long

using namespace std;

const int MaxN = 5e4 + 10;
const double eps = 1e-7;

int f[MaxN], s[MaxN], p[MaxN], y[MaxN], x[MaxN], o[MaxN], tot, n, l, len;

bool Check(int d, int e) {
  if (y[s[d + 1]] == -1e18 && x[s[d + 1]] == -1e18) {
    return 1;
  }
  return (y[s[d + 1]] - y[s[d]]) > e * (x[s[d + 1]] - x[s[d]]);
}

signed main() {
  cin >> n >> len;
  for (int i = 1; i <= n; i++) {
    cin >> p[i], p[i] += p[i - 1], x[i] = p[i] + i;
  }
  x[n + 1] = -1e18, y[n + 1] = -1e18;
  f[1] = (p[1] - len) * (p[1] - len), s[++tot] = 1, o[1] = x[1] - len - 1, y[1] = f[1] + x[1] * x[1];
  for (int i = 2; i <= n; i++) {
    int l = 1, r = tot;
    s[tot + 1] = n + 1;
    /*for (int j = 1; j <= tot; j++) {
      cout << s[j] << " ";
    }
    cout << endl;*/
    o[i] = x[i] - len - 1;
    while (l < r) {
      int mid = (l + r) >> 1;
      Check(mid, 2 * o[i]) ? r = mid : l = mid + 1;
    }
    l = s[l];
    f[i] = min(o[i] * o[i] + y[l] - 2 * o[i] * x[l], (p[i] + i - 1 - len) * (p[i] + i - 1 - len)), y[i] = f[i] + x[i] * x[i];
    //cout << T(y[1], y[2], x[1], x[2]) << " " << f[i] << " " << o[i] << " " << y[l] << " " << x[l] << ' ' << l << endl;
    while (tot > 1 && (y[s[tot]] - y[s[tot - 1]]) * (x[i] - x[s[tot]]) > (y[i] - y[s[tot]]) * (x[s[tot]] - x[s[tot - 1]])) {
      tot--;
    }
    s[++tot] = i;
  }
  cout << f[n] << endl;
  return 0;
}

标签:2r,int,len,斜率,MaxN,tot,优化
From: https://www.cnblogs.com/ybtarr/p/17995200

相关文章

  • 接口压力测试常用的性能指标,接口优化的点,分布式锁的方案常用的方案
    1.接口压力测试常用的性能指标2.接口优化的点3.实现分布式锁的方案常用的方案一.接口压力测试常用的性能指标:1、吞吐量吞吐量是系统每秒可以处理的事务数,也称为TPS(TransactionPerSecond)。比如:一次点播流程,从请求进入系统到视频画图显示出来这整个流程就是一次事务。所以......
  • Unity-GC优化相关笔记
    Unity官网GC定义如下创建对象、字符串或数组时,用于存储它的内存是从称为堆的中央池分配的。当此项不再使用时,其先前占用的内存可被回收并用于其他目的。在过去,通常由程序员通过适当的函数调用显式地分配和释放这些堆内存块。如今,Unity的Mono引擎等运行时系统会自动为您管理内......
  • 给你一颗“定心丸”——记一次由线上事故引发的Log4j2日志异步打印优化分析
    一、内容提要自知是人外有人,天外有天,相信对于Log4j2的异步日志打印早有老师或者同学已是熟稔于心,优化配置更是信手拈来,为了防止我在这里啰里八嗦的班门弄斧,我先将谜底在此公布:log4j2.asyncQueueFullPolicy=Discard&log4j2.discardThreshold=ERROR,这两个Log4j2配置在强依赖的RPC......
  • C#对象二进制序列化优化:位域技术实现极限压缩
    目录1.引言2.优化过程2.1.进程对象定义与初步分析2.2.排除Json序列化2.3.使用BinaryWriter进行二进制序列化2.4.数据类型调整2.5.再次数据类型调整与位域优化3.优化效果与总结1.引言在操作系统中,进程信息对于系统监控和性能分析至关重要。假设我们需要开发一个监控程序,该......
  • 通达信极品抄底优化指标公式源码副图
    X_1:=(2*CLOSE+HIGH+LOW)/4;X_2:=LLV(LOW,5);X_3:=HHV(HIGH,5);X_4:=Ema((X_1-X_2)/(X_3-X_2)*100,5);X_5:=(CLOSE-LLV(LOW,9))/(HHV(HIGH,9)-LLV(LOW,9))*100;X_6:=SMA(X_5,3,1);X_7:=SMA(X_6,3,1);X_8:=3*X_6-2*X_7;X_9:=X_8<(-10);X_10:=REF(X_9,1)=1ANDX_9=......
  • Prompt实战优化
    1.概述在深度学习领域,Prompt(提示语)被广泛应用于自然语言处理任务中,如文本生成、机器翻译和问答系统等。Prompt的设计对模型的性能和生成结果有着重要的影响,因此在实际应用中合理而有效地利用Prompt是提升模型表现的关键策略之一。本篇博客笔者将为大家介绍如何通过反复修改Prompt......
  • 深蓝词库转换3.1版本发布——支持新版搜狗bin用户词库及更多功能优化
    经过单单nopdan这段时间的努力,我们终于迎来了深蓝词库转换3.1版本的发布。在这个版本中,我们增加了对新版搜狗用户词库的支持,并针对用户反馈的问题进行了一系列的优化和修复。下面就让我来为大家详细介绍这个版本的亮点。亮点深蓝词库转换3.1版本发布包含了以下修改:支持新版搜......
  • 通达信大盘平衡仪优化版指标公式源码
    {指标介绍:红色大盘指数安全,绿色大盘指数调整,红箭头超跌,绿箭头超涨,分析大盘不错的工具。}总家数:=INDEXADV+INDEXDEC;多:=INDEXADV;空:=INDEXDEC;差:=INDEXADV-INDEXDEC;起稳:=Ema(EMA(多,3),5);失衡:=EMA(EMA(EMA(空,4),4),2);生命:=EMA(MA(LLV(起稳,5),3),3);平衡差:=起......
  • 如果在循环中不改变vector的大小,C++编译器是否会将.size()优化为常数?
      在C++中,可以使用以下代码计算vector<int>中所有元素的和:vector<int>v={1,3,7,9};sums=0;for(inti=0;i<v.size();i++){sums+=v[i];}  这是一段很普通的代码,问题在于:在这段代码中,v.size()会在循环开始前仅计算一次?还是会在每次循环中都计算一次......
  • MyBatis注解模式和优化
    MyBatis注解模式之前我们使用xml文件方式实现sql语句的编写,我们也可以使用注解模式编写sql语句。前面的基本配置一致,不再叙述。第一步:创建实体类根据数据库的列名与表名设计实体类数据库信息:(表名t_student)实体类:@Data@NoArgsConstructor@AllArgsConstructorpubliccla......