算法学习——决策单调性优化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> <…

HP Instant Information

HP Instant Information before HP-UX 11i v3 《管理系统和工作组&#xff1a;HP-UX系统管理员指南》 After HP-UX 11i v3 《HP-UX系统管理指南》(由多个文档组成的文档集) 《HP-UX系统管理员指南&#xff1a;概述》 《HP-UX系统管理员指南&#xff1a;配置管理》 《HP-UX系统管…

CodeForces 258D Little Elephant and Broken Sorting(期望)

CF258D Little Elephant and Broken Sorting 题意 题意翻译 有一个\(1\sim n\)的排列&#xff0c;会进行\(m\)次操作&#xff0c;操作为交换\(a,b\)。每次操作都有\(50\%\)的概率进行。 求进行\(m\)次操作以后的期望逆序对个数。 \(n,m\le 1000\) 输入输出格式 输入格式&#x…

记一次vue项目yarn打包环境配置失效的解决方案

项目中使用到了yarn打包工程&#xff0c;主要有以下几个命名。 # build for production with minification yarn run build# build for production and view the bundle analyzer report yarn run build --report# 自定义API地址 baseurl"http://127.0.0.1:8080/api/&quo…

数字签名与HTTPS详解

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

[BZOJ4320][ShangHai2006]Homework(根号分治+并查集)

对于<sqrt(300000)的询问&#xff0c;对每个模数直接记录结果&#xff0c;每次加入新数时暴力更新每个模数的结果。 对于>sqrt(300000)的询问&#xff0c;枚举倍数&#xff0c;每次查询大于等于这个倍数的最小数是多少&#xff0c;这个操作通过将询问逆序使用并查集支持。…

VScode 结局插件prettier和vetur格式化冲突

先上配置代码 {"workbench.iconTheme": "vscode-icons","workbench.startupEditor": "newUntitledFile","workbench.colorTheme": "One Dark Pro","editor.fontSize": 14,"editor.tabSize":…

WPF效果(GIS三维续篇)

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

vue 表单 验证 async-validator

1、使用插件async-validator async-validator 地址&#xff1a;https://github.com/yiminghe/async-validator 2、示例&#xff08;vueelement-ui&#xff09; <el-form :model"numberValidateForm" ref"numberValidateForm" label-width"100px&qu…

[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浏览器…

CSRFGuard工具介绍

理解CSRFGuard的基础&#xff1a;http://www.runoob.com/jsp/jsp-tutorial.html 1&#xff1a;您需要做的第一件事是将OWASP.CSRFARGAD.JAR库复制到类路径中。放置Owasp.CsrfGuard.jar最常见的类路径位置在Web应用程序的WEB-INF文件夹的lib目录中。 OWASP CSRFGARD 3在传统Java…

[19/04/24-星期三] GOF23_创建型模式(建造者模式、原型模式)

一、建造者模式 本质&#xff1a;分离了对象子组件的单独构造(由Builder负责)和装配的分离(由Director负责)&#xff0c;从而可以构建出复杂的对象&#xff0c;这个模式适用于&#xff1a;某个对象的构建过程十分复杂 好处&#xff1a;由于构建和装配的解耦&#xff0c;不同的构…

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

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

js 转义

1. JavaScript 特殊字符 2. 正反斜杠互相替换 a/b/c.replace(/\//g,\\) // "a\b\c" $0.value.replace(/\\/g,\/) // a/b/c 获取到 而不提取出 某个值后进行直接处理 \ 有转义功能&#xff0c;所以一旦解析必然转义&#xff0c;通常是直接获取到数据源…

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

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

ie兼容响应式布局的实现总结

虽然说响应式设计的理想状态是&#xff0c;需对pc/移动各种终端进行响应&#xff1b;但是现实是高分辨率的pc端与手机终端屏幕相差太大&#xff0c;像电商这样有大量图片和文字 信息的同时排版要求精准的页面&#xff0c;设计一个同时适应高分辨率pc又适合小尺寸的手机终端是挑…

Luogu P1471 方差

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

python学习day17 递归函数

递归函数 http://www.cnblogs.com/Eva-J/articles/7205734.html def age(n):if n 4:return 40elif n >0 and n < 4:return age(n1) 2print(age(1)) # 46 只要写递归函数&#xff0c;必须要有结束条件。 二分法查找 l [2,3,5,10,15,16,18,22,26,30,32,35,41,42,43,55,5…

2018年最好用的20个Bootstrap网站模板

Bootstrap是目前最受欢迎也是最简洁的建站方式之一&#xff0c;尤其是伴随移动端的发展&#xff0c;响应式设计已经毫无疑问成为了网页设计的趋势&#xff0c;网站建设要求兼容手机端已经是一种刚需&#xff0c;也成为提升用户体验的一种必要方式。但这无疑会加大设计师和前端人…