线性规划做法

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

以下 \(\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. 入门级java开发环境的配置安装

    为了能够在计算机上开发Java程序和运行Java程序,就需要在Windows操作系统上配置Java开发环境. 首先,安装JDK: 1.在Oracle官网上下载JavaSE: 2.在Download下载 ...

  2. Java's absolute and relative path

    在java中文件目录中带"/"的是绝对路径,不带"/"的是相对路径. 请求页面的写法,在web中,页面路径主要写的有以下几种 1.重定向 2.转发 3.超链接 ...

  3. 创建function函数sys_guid时报错

    创建function函数sys_guid时报错 执行下面的命令 show variables like 'log_bin_trust_function_creators';set global log ...

  4. (Linux)不挂断启动进程

    环境:腾讯云Ubuntu x86_64 问题:在配置应用时,需要让他后台启动,关闭ssh连接也要可以保持后台运行 解决办法: 1.使用nohup 参考链接:https://zhuanlan.zhihu ...

  5. Svn安装客户端鼠标右键报错SendRpt.exe not found

    kill 掉 重启资源管理器就好了

  6. NX二次开发 拔模增量计算工具

    在塑胶模具设计行业拔模增量计算经常都需要用到,平常都是利用计算器工具或者外部的计算工具去算.曾经有一个模具设计的培训老师把拔模增量计算工具称为模具设计的神器,好吧,我也造个神器.-_-! VS2019 ...

  7. pip第三方库安装失败原因及解决办法

    pip安装三方库失败原因及解决方法 提示:WARNING: You are using pip version 20.2.3, however version 20.2.4 is available. ...

  8. Javaweb项目和Maven项目的相关导包

    Javaweb项目的学习大致需要一下几个导包: 以上几个包需要导入到WEB-INF目录下的lib文件夹里面,主要操作如下: 1.新建一个lib文件夹(在WEB-INF目录下) 2.右键lib文件夹,选 ...

  9. Python学习笔记--判断语句的延续

    if else语句 示例: 需要注意的是,if后面必须有条件,而else后面可以不需要判断条件 案例: 实现: if elif else 语句 多条件判断,if 和 elif 后面必须有条件,else ...

  10. 对于Java课上问题的探究和解答

    问题一:子类和父类的继承关系(extends) 需要强调的是,子类自动声明继承父类中的public和protected的成员 其中,public成员,外界可以自由访问: private成员,外界无法进 ...