算法学习——决策单调性优化DP

update in 2019.1.21 优化了一下文中年代久远的代码 的格式……

 

什么是决策单调性?

在满足决策单调性的情况下,通常决策点会形如1111112222224444445555588888.....

即不可能会出现后面点的决策点小于前面点的决策点这种情况。

那么这个性质应该如何使用呢?

 1,二分。

  考虑到决策点单调递增,因此我们考虑用单调队列存下当前的决策选取情况。

  单调队列中存的量会带3个信息:这是哪个决策点,这个决策点会给哪个区间的点产生贡献(这是一个区间,所以算2个信息)

  相当于队列中存了很多个区间,假设当前的决策点是这样的:1111112222222333333,

  现在插入4这个决策,那么我们就是要找到最靠左的合法位置将决策序列变为类似这样的序列:111111222222444444444,

  因为决策单调,所以要覆盖肯定是一整段一整段的覆盖,因此我们先判断4是否可以覆盖完3这个区间,只需要看3的左端点是否可以被替换即可。

  我们重复覆盖整个区间这个操作,直到有个区间无法被完整覆盖,或者已经到了不合法的位置(因为第x个点只能给区间[x + 1, n]内的点产生贡献)。

  如果这个区间无法被完整覆盖,那么我们就在这个区间内二分找到最靠左的点使得4可以替换掉这个区间内的数,然后修改管理这个区间的数的区间,把被覆盖的区间让给4.

  每次操作前弹掉已经没有用的决策点,于是可以实现O(1)转移。(例如当前队首的决策点可以更新[3, x-1]这个区间,但我们已经枚举到x了,所以这个决策点显然就没有什么用了)  

  以下是某个年代久远的一道决策单调性优化的代码。

 

 1 /*[NOI2009]诗人小G by ww3113306*/
 2 #include<bits/stdc++.h>
 3 using namespace std;
 4 #define R register int
 5 #define AC 100100
 6 #define LL long long
 7 #define LD long double
 8 #define ac 101000
 9 #define inf 1000000000000000000LL
10 int t, L, p, n;
11 int Next[AC], s[AC], last[AC], l[AC], r[AC];//对应决策的管理区间,Next对last进行相反操作,以便输出
12 int q[AC], head, tail;//存下当前是哪个决策
13 LD f[AC];
14 LL sum[AC];
15 char ss[ac][45];
16 
17 inline LD qpow(LD x)//error!!!x也要用LD!!!
18 {
19     LD ans = 1;int have = p;
20     while(have)
21     {
22         if(have & 1) ans *= x;
23         x *= x, have >>= 1;
24     }
25     return ans;
26 }
27 
28 inline LD count(int x, int j){return f[j] + qpow(abs(sum[x] - sum[j] - L - 1));}//j --- > x
29 
30 inline void pre()
31 {
32     scanf("%d%d%d", &n, &L, &p);
33     for(R i = 1; i <= n; i ++)
34     {
35         scanf("%s", ss[i] + 1);
36         s[i] = strlen(ss[i] + 1) + 1;//加上后面的空格
37         sum[i] = sum[i-1] + s[i];//求出前缀和
38     }    
39 }
40 
41 void half(int x)//二分查找
42 {
43     int now = q[tail], ll = max(l[now], x + 1), rr = n, mid;//因为可能可以覆盖多个区间
44     while(ll < rr)
45     {
46         mid = (ll + rr) >> 1;
47         if(count(mid, x) < count(mid, now)) rr = mid;//如果更优就往左缩短
48         else ll = mid + 1;//不然就向右寻找
49     }
50     r[q[tail]] = ll - 1;
51     q[++tail] = x, l[x] = ll, r[x] = n;
52 }
53 
54 inline void getans()
55 {
56     head = 1, tail = 1, q[1] = 0, l[0] = 1, r[0] = n;
57     for(R i = 1; i <= n; i ++)
58     {
59         while(r[q[head]] < i) ++head;//如果当前队首已经取不到了
60         int now = q[head];
61         f[i] = count(i, now);//error ??? 用函数的话会爆了会自动转换为inf?
62         last[i] = now;
63         if(count(n, q[tail]) < count(n, i)) continue;//如果最后一个都不够优,那就不二分了
64         while(count(l[q[tail]], q[tail]) > count(l[q[tail]], i)) --tail;//如果当前可以覆盖前面的整个区间
65         half(i);//注意上面的while要在调用half之前修改,这样取到的now才是正确的
66     }
67 }
68 
69 inline void write()
70 {
71     if(f[n] > inf) puts("Too hard to arrange");
72     else
73     {
74         printf("%lld\n", (LL)(f[n] + 0.5));//注意精度误差
75         for(R i = n; i; i = last[i]) Next[last[i]] = i;
76         int now = 0;
77         for(R i = 1; i <= n; i ++)
78         {
79             now = Next[now];//now先跳了吧
80             int be = now;//先只到这行结尾,因为for还要加的
81             for(R j = i; j < be; j ++) printf("%s ", ss[j] + 1);
82             printf("%s\n", ss[be] + 1), i = be;//最后再赋i,因为for中还要用到当前i
83         }
84     }
85     puts("--------------------");
86 }
87 
88 int main()
89 {
90     scanf("%d", &t);
91     while(t--) pre(), getans(), write();
92     return 0;
93 }
View Code

 

 2,分治

  假设我们当前的被决策区间是[l, r], 决策点区间是[ll, rr],那么我们取被决策区间的中点mid = (l + r) >> 1,然后在[ll, rr]中暴力寻找mid的最优决策点k,于是根据决策单调性,我们有:

  被决策区间[l, mid - 1]对应的决策点区间是[ll, k].同理,被决策区间[mid + 1, r]对应的决策点区间是[k, rr],于是我们就将这个区间划分为了2半,不断向下递归减小决策点范围即可用正确的复杂度求出所有的转移。

 

转载于:https://www.cnblogs.com/ww3113306/p/9889295.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/249104.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SVG画一个箭头

参考菜鸟手册&#xff1a; https://www.runoob.com/svg/svg-tutorial.html 打开菜鸟中的在线工具 在可视化截图拖拉元素绘制箭头 点击command U 查看源码 将源码拷入html代码中&#xff0c;查看效果 最后&#xff0c;贴出源码供大家参考 <!DOCTYPE html> <…

数字签名与HTTPS详解

因为HTTP协议本身存在着明文传输、不能很好的验证通信方的身份和无法验证报文的完整性等一些安全方面的确点&#xff0c;所以才有了HTTPS的缺陷。HTTPS确切的的说不是一种协议&#xff0c;而是HTTP SSL (TSL)的结合体。HTTP报文经过SSL层加密后交付给TCP层进行传输。SSL(安全套…

WPF效果(GIS三维续篇)

去年这个时候简单的摸索了一下三维的GIS相关的东西,也就是仅仅玩耍了一把,这次来点真正用的上的干货效果效果&#xff1a; 1、加载自定义百度样式的瓦片效果 2、加载自定义百度样式的缩放效果 3、快速手动进去咱的大帝都 4、加载海量Mark效果 5、加载海量Mark和简单模型效果 6、…

[19/04/23-星期二] GOF23_创建型模式(工厂模式、抽象工厂模式)

一、工厂模式(分为&#xff1a;简单工厂模式、工厂方法模式、抽象工厂模式) 实现了创建者和调用者的分离 核心本质&#xff1a;1、实例化对象&#xff0c;用工厂方法代替new操作&#xff1b;2、将选择实现类、创建对象统一管理和控制&#xff0c;从而将调用者跟实现类解耦。 简…

Chrome浏览器12px问题-webkit-text-size-adjust: none 已失效的解决方案

对于早期的chrome, 如果要想显示12px以下的字体&#xff0c;一般通用的方案都是在对应的元素中添加 div {-webkit-text-size-adjust: none; }但是我今天遇到的需求&#xff0c;添加了之后没有反应&#xff0c;而且浏览就根本不支持这种写法。 在网上看到了博客《Chrome浏览器…

深入理解vue中的slot与slot-scope

写在前面 vue中关于插槽的文档说明很短&#xff0c;语言又写的很凝练&#xff0c;再加上其和methods&#xff0c;data&#xff0c;computed等常用选项在使用频率、使用先后上的差别&#xff0c;这就有可能造成初次接触插槽的开发者容易产生“算了吧&#xff0c;回头再学&#…

关于Java抽象类,接口与实现接口及派生类继承基类

1. 抽象类 抽象类就是有一个或多个方法只被声明而未被实现。 抽象方法的声明以分号结束&#xff0c;并且用关键字abstract来说明它以标识它为抽象方法。 格式&#xff1a; public abstract class 类名{ 定义变量// 抽象方法// } 2. 接口是抽象类的一种&#xff0c;之包含常量…

Luogu P1471 方差

题目传送门 开了十倍空间才过是什么鬼&#xff1f;该不会我线段树炸了吧……细思极恐 平均数都会求&#xff0c;维护区间和&#xff0c;到时候除一下就好了。 方差的求法如下(用的Luogu的图片) 因为要维护一个平方&#xff0c;我们可以考虑使用van♂完全平方公式将它拆开&#…

Android SDK 2.3/3.0/4.0/4.2 下载与安装教程

Eclipse下搭建Android开发环境教程&#xff1a;http://dev.son1c.com/show/1253.html Google已经发布了Android SDK 4.2版本.下面给朋友们介绍一下安装 Android 模拟器 Emulator模拟器的方法: 1、首先确定安装了Java JDK&#xff0c;如果没有&#xff0c;可以去http://www.ora…

浏览器渲染原理与过程

一、浏览器如何渲染网页 要了解浏览器渲染页面的过程&#xff0c;首先得知道一个名词——关键路径渲染。关键渲染路径&#xff08;Critical Rendering Path&#xff09;是指与当前用户操作有关的内容。例如用户在浏览器中打开一个页面&#xff0c;其中页面所显示的东西就是当前…

深入理解CSS盒模型 - 程序猿的程 - 博客园

深入理解CSS盒模型 本文是学习中传思客在慕课网开的课程《前端跳槽面试必备技巧》的学习笔记。课程地址&#xff1a;https://coding.imooc.com/class/evaluation/129.html#Anchor。 如果你在面试的时候面试官让你谈谈对盒模型的理解&#xff0c;你是不是不知从何谈起。这种看似…

线程死锁问题

1 package com.demo.bingfa;2 3 /**4 * java并发编程中&#xff0c;死锁的概念5 *6 * 我们启用了两个线程&#xff0c;分别抢占2个资源&#xff0c;但这两个资源又分别被不同的对象&#xff08;字符串&#xff09;锁住了。7 * 当第一个线程调用 resource1 方法&#xff0c;…

使用PM2搭建在线vue.js开发环境(以守护进程方式热启动)

项目以vue.jslayUI的作为前端开发技术栈&#xff0c;需要有一个在线的环境供项目成员实时查看效果&#xff0c;总不能每次都webpack打包发布后才能看到效果吧&#xff01;刚开始就简单使用npm run dev命令热启动&#xff0c;但是shell命令窗口退出后&#xff0c;热启动也就失效…

zabbix实现mysql数据库的监控

先来介绍zabbix中几个常用的术语&#xff1a; 主机&#xff08;host&#xff09;&#xff1a; 要监控的网络设备&#xff0c;可由ip或DNS名称指定。 主机组&#xff08;host group&#xff09;&#xff1a; 主机的逻辑容器&#xff0c;可以包含主机和模板&#xff…

VSCode配合eslint进行JavaScript质量检查

写在开始前&#xff1a;如有不准确的地方希望大家提出&#xff0c;文章可以改知识不能错。 创建一个项目 这里已node项目为例 npm init 根据提示填写相关信息 安装eslint npm install eslint --save也可以全局安装 npm install eslint -g初始化 eslint文件 eslint --init执行命…

未找到导入的项目,请确认 Import 声明中的路径正确

VS2017打开以前vs版本开发的项目 <Import Project"$(MSBuildBinPath)\Microsoft.CSharp.targets" /> <Import Project"$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v12.0\WebApplications\Microsoft.WebApplication.targets" /> 修改V12…

bzoj [Usaco2009 Hol]Cattle Bruisers 杀手游戏

Description Input 第1行输入N&#xff0c;R&#xff0c;BX&#xff0c;BY, BVX&#xff0c;BVY&#xff0c;之后N行每行输入四个整数Xi&#xff0c;Yi&#xff0c;VXi&#xff0c;VYi&#xff0e; Output 一个整数&#xff0c;表示在逃脱过程中&#xff0c;某一个时刻最多有这…

Visual Studio Code 使用 ESLint 增强代码风格检查 - gyzhao - 博客园

前言 在团队协作开发中&#xff0c;为了统一代码风格&#xff0c;避免一些低级错误&#xff0c;应该设有团队成员统一遵守的编码规范。很多语言都提供了Lint工具来实现这样的功能&#xff0c;JavaScript也有类似的工具&#xff1a;ESLint。除了可以集成到构建工具中(如&#x…

eclipse下使用git插件上传代码至github

eclipse下使用git插件上传代码至github 1.eclipse下安装git 正常情况下&#xff0c;eclipse 是自带 git 插件的&#xff0c;那么即可跳至步骤1的最后一小步&#xff0c;配置 git 。 如果十分悲剧&#xff0c;你的 eclipse 中见不到 git 的身影&#xff0c;那么也没关系&#…

VS(C++)配置Halcon(一次配置,永久使用)

【说明】只需配置一次&#xff0c;以后新项目无需再次配置。 本教程是64位版本&#xff0c;32位可参考本教程。VS与Halcon无论哪个版本&#xff0c;都可参考本教程。 【步骤】以VS2015Halcon18.11为例 1、新建一个C|Win32控制台应用程序项目 2、视图|其他窗口|属性管理器 在 De…