线性规划做法

同时也作为线性规划对偶的一个小小的学习笔记。

以下 \(\cdot\) 表示点积,\(b,c,x,y\) 是行向量。

\(A\) 是矩阵,对于向量 \(u,v\) 若 \(\forall i,u_i\leq v_i\) 则称 \(u\leq v\),\(\geq\) 同理。

线性规划标准型:

\[\max c\cdot x\\
s.t.
\left\{
\begin{aligned}
&Ax\leq b \\
&x\geq 0
\end{aligned}
\right.
\]

它的对偶是:

\[\min b\cdot y \\
s.t.
\left\{
\begin{aligned}
&A^Ty\geq c \\
&y\geq 0
\end{aligned}
\right.
\]

弱对偶定理:\(\max c\cdot x \leq \min b\cdot y\)。

我们可以任意取可行域中的 \(x,y\),然后对于 \(y^TAx\) 一方面由于 \(y^T\) 非负有 \(y^TAx\leq y^T b=b\cdot y\),另一方面 \(y^TAx=(yA^T)^Tx\geq c^Tx=c\cdot x\),即得证。

强对偶定理:\(\max c\cdot x = \min b\cdot y\)。也就是说我们可以把线性规划转为其对偶问题进行求解。

回到这道题,给每一个区间的每一种操作编号 \(1\sim M\),对于第 \(t\) 个操作设其下标集合为 \(I_t\),我们建一个变量 \(x_t\),表示这个操作重复做的次数。我们放宽 \(x_t\in R\),可以证明最优解仍然是整数。

将取等条件拆成两个条件,那么答案是:

\[\min \sum_{t=1}^M x_t\\
s.t.
\left\{
\begin{aligned}
&\sum_{t=1}^{M} [i\in I_t] x_t\geq a_i \\
&-\sum_{t=1}^{M} [i\in I_t] x_t\geq -a_i \\
&x_t\geq 0
\end{aligned}
\right.
\]

对偶一下,有:

\[\max \sum_{i=1}^n a_i(p_i-q_i)\\
s.t.
\left\{
\begin{aligned}
&\sum_{i=1}^{n} [i\in I_t](p_i-q_i)\leq 1 \\
&p_i,q_i\geq 0
\end{aligned}
\right.
\]

容易发现 \(p_i-q_i\) 可以取任意实数,设 \(y_i=p_i-q_i\),有:

\[\max \sum_{i=1}^n a_i y_i\\
s.t. \sum_{i=1}^{n} [i\in I_t]y_i\leq 1
\]

这里 yhx 大佬的博客中讲此矩阵是全单模矩阵,也就是说线性规划可行域的顶点全是整数所以这个线性规划具有整数性?不太了解什么是全单模 QAQ。

既然有整数性,那么考虑拿着这个东西做。该线性规划的实际意义是让我们对每个位置赋权,使得每种操作下标的权值之和都 \(\leq 1\)。

经典套路,类似最大子段和,记录三种操作后缀和的最大值 \(x,y,z\) 来 DP。由限制有 \(x,y,z\leq 1\)。而如果有 \(x/y/z<0\),那么我们就需要”截断“然后新开一个后缀。同时这也说明了 \(y_i\) 有意义的取值只有 \(0,1,-1\),\(<-1\) 的都是”截断“而总权值没有 \(-1\) 优秀所以一定不会取。

时间复杂度 \(O(n)\) 带 \(24\) 的常数。

#include <cstdio>
#include <algorithm>
#define forxyz \
for(int x=0;x<2;++x) \
for(int y=0;y<2;++y) \
for(int z=0;z<2;++z)
using namespace std;
int read(){
char c=getchar();int x=0;
while(c<48||c>57) c=getchar();
do x=(x<<1)+(x<<3)+(c^48),c=getchar();
while(c>=48&&c<=57);
return x;
}
typedef long long ll;
const int N=100003;
const ll INF=0x3f3f3f3f3f3f3f3f;
int n;
int a[N];
ll f[N][2][2][2];
void solve(){
n=read();
for(int i=1;i<=n;++i) a[i]=read();
for(int i=1;i<=n;++i) forxyz f[i][x][y][z]=-INF;
f[0][0][0][0]=0;
for(int i=1;i<=n;++i){
forxyz{
for(int d=-1;d<=1;++d){
if(x+d>1||y+d>1) continue;
ll &dp=f[i][max(x+d,0)][z][max(y+d,0)];
dp=max(dp,f[i-1][x][y][z]+d*a[i]);
}
}
}
ll res=0;
forxyz res=max(res,f[n][x][y][z]);
printf("%lld\n",res);
}
int main(){
int tc=read();
while(tc--) solve();
return 0;
}

贪心做法

解析咕了,具体看洛谷题解区。

#include <cstdio>
#include <algorithm>
using namespace std;
int read(){
char c=getchar();int x=0;
while(c<48||c>57) c=getchar();
do x=(x<<1)+(x<<3)+(c^48),c=getchar();
while(c>=48&&c<=57);
return x;
}
typedef long long ll;
void solve(){
int n=read();
ll a=0,b=0,c=0,res=0,las=read();
for(int i=2;i<=n+1;++i){
ll x=0;
if(i<=n) x=read();
ll dlt=0;
if(x<a+b){
dlt=a+b-x;
if(a<dlt) b-=dlt-a,dlt=a;
if(b<dlt) a-=dlt-b,dlt=b;
a-=dlt;b-=dlt;x-=dlt;
}
x-=a+b;
ll mn=min(las,x);
res+=mn;las-=mn;x-=mn;a+=mn;
res+=las;c+=las;
x+=dlt;res-=dlt;
las=x;
swap(b,c);
}
printf("%lld\n",res);
}
int main(){
int tc=read();
while(tc--) solve();
return 0;
}

[ZJOI2020] 序列 线性规划做法/贪心做法的更多相关文章

  1. [HNOI2005]狡猾的商人 ,神奇做法——贪心

    洛谷P2294 [HNOI2005]狡猾的商人 ,神奇做法--贪心 看到大牛都是写的差分约束或带权并查集,本蒟蒻都不太会(还是用差分约束过了的QAQ),但是想出一种贪心的策略,运用神奇的优先队列实现. ...

  2. 【t081】序列长度(贪心做法)

    Time Limit: 1 second Memory Limit: 128 MB [问题描述] 有一个整数序列,我们不知道她的长度是多少(即序列中整数的个数),但我们知道在某些区间中至少有多少个整数 ...

  3. hdu4737 A Bit Fun ——O(n)做法、错误的做法 + 正确做法

    囧== 下面的做法是错误的.下午在路上突然明白了== 哎,到现在还是只知道暴力的做法,囧爆了:http://www.cnblogs.com/liuxueyang/p/3322197.html 类似于前 ...

  4. 求序列完美度(trie+贪心)

    题目链接: 求序列完美度 题目描述 给出由n个数组成的序列s,规定第i个数s[i]到第j个数s[j]组成的子序列的完美度为该子序列中所有数的和与任意一个不在该子序列中的数进行异或运算得到的值中的最大值 ...

  5. 【BZOJ1345】[Baltic2007]序列问题Sequence 贪心+单调栈

    [BZOJ1345][Baltic2007]序列问题Sequence Description 对于一个给定的序列a1, …, an,我们对它进行一个操作reduce(i),该操作将数列中的元素ai和a ...

  6. 【bzoj1283】序列 线性规划与费用流

    题目描述 给出一个长度为 的正整数序列Ci,求一个子序列,使得原序列中任意长度为 的子串中被选出的元素不超过K(K,M<=100) 个,并且选出的元素之和最大. 输入 第1行三个数N,m,k. ...

  7. 洛谷 P5470 - [NOI2019] 序列(反悔贪心)

    洛谷题面传送门 好几天没写题解了,写篇题解意思一下(大雾 考虑反悔贪心,首先我们考虑取出 \(a,b\) 序列中最大的 \(k\) 个数,但这样并不一定满足交集 \(\ge L\) 的限制,因此我们需 ...

  8. XDU 1037 倍流畅序列(字符串匹配+贪心)

    题目描述 对于一个0,1串s, 从左端开始读取它的0获得序列s0,从右端开始读取它的1获得s1,如果s0与s1同构,则称s为倍流畅序列.例如:011001是一个倍流畅序列, 因为:s0 = 0__00 ...

  9. Project Euler 29 Distinct powers( 大整数质因数分解做法 + 普通做法 )

    题意: 考虑所有满足2 ≤ a ≤ 5和2 ≤ b ≤ 5的整数组合生成的幂ab: 22=4, 23=8, 24=16, 25=3232=9, 33=27, 34=81, 35=24342=16, 4 ...

  10. 【UOJ】【UR #2】猪猪侠再战括号序列(splay/贪心)

    http://uoj.ac/problem/31 纪念伟大的没有调出来的splay... 竟然那个find那里写错了!!!!!!!!!!!!! 以后要记住:一定要好好想过! (正解的话我就不写了,太简 ...

随机推荐

  1. 前端基础复习之HTML

    1.web基础知识 1 1.Web基础知识 2 1.Internet 3 1.简介 4 Internet 实际上就是由计算机所组成的网络结构 5 6 服务: 7 1.Telnet 8 远程登录 9 2 ...

  2. linux : root  密码忘记,解决办法

    1.重启 2.在启动选择系统内核界面,按e键进入单用户模式 3.找到linux16(或者linux) 开头行,删除ro,并且在ro处添加 rw init=/sysroot/bin/sh 4.按 ctr ...

  3. angularJS:一个页面多个ng-app

    var app = angular.module('myApp', []); app.controller('myCtrl', function($scope, $rootScope) { $scop ...

  4. React16下报错引发整个页面crash的解决方法

    如果报错没有没有被catch,将会引起整个React组件树的unmounting 解决方法:在生命周期中增加componentDidCatch https://reactjs.org/blog/201 ...

  5. 一文快速回顾 Servlet、Filter、Listener

    什么是Servlet? 前置知识: Web 服务器:可以指硬件上的,也可以指软件上的.从硬件的角度来说, Web 服务器指的就是一台存储了网络服务软件的计算机:从软件的角度来说, Web 服务器指的是 ...

  6. python渗透测试入门——Scapy库

    Scapy 是一个用来解析底层网络数据包的Python模块和交互式程序,该程序对底层包处理进行了抽象打包,使得对网络数据包的处理非常简便.该类库可以在在网络安全领域有非常广泛用例,可用于漏洞利用开发. ...

  7. 杂谈--User Story

    本篇用于给自己后续慢慢看,对敏捷感兴趣的小伙伴,可以自行去看官方文档或者各种网站的视频讲解,更详细. 对于敏捷开发来说,User Story是开发的基础,把原本需求拆成最小粒度的Story,以方便拆分 ...

  8. Java面试——Tomcat

    更多内容,前往个人博客 一.Tomcat 顶层架构 ​ Tomcat 中最顶层的容器是 Server,代表着整个服务器,从上图中可以看出,一个 Server可以包含至少一个 Service,用于具体提 ...

  9. Teamcenter_NX集成开发:通过NXOpen查询零组件是否存在

    之前用过NXOpen PDM的命名空间下的类,现在记录一下通过PDM命名空间下的类查询Teamcenter零组件的信息,也可以用来判断该零组件是否存在. 1-该工程为DLL工程,直接在NX界面调用,所 ...

  10. 在windows系统中设置MySQL数据库

    MySQL搭建 效果图 step1:下载安装包 https://downloads.mysql.com/archives/community/ step2:解压后即完成安装 step3:创建 my.i ...