dp优化1——sgq(单调队列)

该文是对dp的提高(并非是dp入门,dp入门者请先参考其他文章)

有时候dp的复杂度也有点大。。。会被卡。

这几次blog大多数会讲dp优化。

回归noip2017PJT4.(题目可以自己去百度)。就是个很好的案例。那题是个二分套dp如果dp不优化复杂度O(n^2logn)还能拿60分(CCF太仁慈了,如果是我直接给10分)。

正解加上个单调队列(其实是sliding window)O(nlogn)

我们发现,此类dp是这样的

状态i是由[l,r]转移过来的。且i在向右移动的过程中,[l,r]一定会跟着往右移,那不就是单调队列吗!!!

至于单调队列都不会的,我在这给一句解释———如果一个人比你小,还比你强,那你就永远比不过他了--chen_zhe大佬

其实是这样的——能转移到i的窗口[l,r]在向右移动的过程中,我们加一个队列,队首的dp值最优,在r向右移动时,遇到一个状态t

写个伪代码

while(队列不空&&t的dp值由于队尾值)弹出队尾元素;将t插入队尾

别忘了,l还要向右移动,右移会导致一些状态离开队列,需要在原队列删除。

OK接下来看例题:

多重背包n个物体,每个numi个,每个物品右价值和重量,求重量不超过m的最大价值(不会o(n^2m)请自行百度,改文不介绍过于基础的dp)。

您会说一句,这种水题我30s切。结果切完后就30分。。。。

一拍脑袋,二进制优化-》O(nmlogn)(将numi分解二进制,再用01做)

结果毒瘤的数据结构大师lxl成功卡掉了您的log(送你《凉凉》x1)

看来只能用O(nm)的做法,先写下dp转移方程

dp[i][j]表示前i个物体,限制重量为j的最大价值

dp[i][j]=max(dp[i-1][j-k*w[i]]+v[i]*k)(0<=k<=num[i])

状压:dp[j]=max(dp[j-k*w[i]]+v[i]*k)

我们先瞎搞:

在i和j都确定的情况下:

设:

n*w[i]+p=j p=j%w[i];

j/w[i]=n(注意是整除)

原方程变为dp[j]=max(dp[j%w[i]+k*w[i]]-k*w[i])+n*w[i](2)

聪明的你一定会了。

这个方程的k与原来的K不同(为区分下文将原来的K大写)

如果你自己推过(2),您会发现k=n-K

这样可以搞出k的范围

0<=n-k<=num[i]

n-num[i]<=k<=n

在j%w【i】不变时max(dp[j%w[i]+k*w[i]]-k*w[i])只与k有关,爽歪歪~~ 单调队列喽。

不懂再想想这张图(important)

没例题总不行!!例题是hdu1171(多重背包裸题)。但出题者非常善良,O(n^2m)也给过了。

单调队列79MS,纯dp1092MS

代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int dp[2][250011],v[500011],num[500011];
int q[10000000],l,r,n;
int main(){//freopen("in.txt","r",stdin);freopen("o1.txt","w",stdout);
    while(scanf("%d",&n)!=EOF && n>=0){
        memset(dp,0,sizeof(dp));memset(v,0,sizeof(v));memset(num,0,sizeof(num));
        l=r=0;
        int i,sum=0,j;
        for(i=1;i<=n;++i)scanf("%d%d",&v[i],&num[i]),sum+=v[i]*num[i];
        int m=sum>>1,p,ans=0;
        for(i=1;i<=n;++i){
            for(p=0;p<v[i];++p){
                int kl,kr;
                l=r=0;l=1;q[++r]=0;
                for(j=p;j<=m;j+=v[i]){
                    int pre=kr;
                    kl=max(j/v[i]-num[i],0),kr=j/v[i];
                    while(l<=r && (q[l]<kl || q[l]>kr))++l;
                    for(int k=pre+1;k<=kr;++k){
                        while(l<=r && dp[i%2^1][j%v[i]+q[r]*v[i]]-q[r]*v[i]<dp[i%2^1][j%v[i]+k*v[i]]-k*v[i])--r;
                        q[++r]=k;
                    }
                    dp[i%2][j]=dp[i%2^1][j%v[i]+q[l]*v[i]]-q[l]*v[i]+(j/v[i])*v[i];
                    ans=max(ans,dp[i%2][j]);
                }
            }
        }
        printf("%d %d\n",sum-ans,ans);
    }
}

原文地址:https://www.cnblogs.com/david--lj/p/8467928.html

时间: 2024-08-01 14:32:34

dp优化1——sgq(单调队列)的相关文章

ZOJ 3632 Watermelon Full of Water(dp+线段树或单调队列优化)

Watermelon Full of Water Time Limit: 3 Seconds      Memory Limit: 65536 KB Watermelon is very popular in the hot summer. Students in ZJU-ICPC Team also love watermelon very much and they hope that they can have watermelon to eat every day during the

常见的DP优化类型

常见的DP优化类型 1单调队列直接优化 如果a[i]单调增的话,显然可以用减单调队列直接存f[j]进行优化. 2斜率不等式 即实现转移方程中的i,j分离.b单调减,a单调增(可选). 令: 在队首,如果g[j,k]>=-a[i],那么j优于k,而且以后j也优于k,因此k可以重队列中直接删去.在队尾,如果x<y<z,且g[x,y]<=g[y,z],也就是说只要y优于x一定可以得出z优于y的,我们就删去y. 经过队尾的筛选,我们在队列中得到的是一个斜率递减的下凸包,每次寻找从上往下被-

每日一dp(1)——Largest Rectangle in a Histogram(poj 2559)使用单调队列优化

Largest Rectangle in a Histogram 题目大意: 有数个宽为1,长不定的连续方格,求构成的矩形中最大面积 /************************************************************************/ /* 思路1. 当前为n的面积如何与n-1相联系,dp[i][j]=max(dp[i-1][k]) , 0<k<=j 描述:i为方块个数,j为高度 但是此题目的数据对于高度太变态,h,1000000000 ,n,1

P3195 [HNOI2008]玩具装箱TOY DP+优化

题目描述 P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京.他使用自己的压缩器进行压缩,其可以将任意物品变成一堆,再放到一种特殊的一维容器中.P教授有编号为1...N的N件玩具,第i件玩具经过压缩后变成一维长度为Ci.为了方便整理,P教授要求在一个一维容器中的玩具编号是连续的.同时如果一个一维容器中有多个玩具,那么两件玩具之间要加入一个单位长度的填充物,形式地说如果将第i件玩具到第j个玩具放到一个容器中,那么容器的长度将为 x=j-i+Sigma(Ck) i<=K<=j

[Vijos 1243]生产产品(单调队列优化Dp)

Description 在经过一段时间的经营后,dd_engi的OI商店不满足于从别的供货商那里购买产品放上货架,而要开始自己生产产品了!产品的生产需要M个步骤,每一个步骤都可以在N台机器中的任何一台完成,但生产的步骤必须严格按顺序执行.由于这N台机器的性能不同,它们完成每一个步骤的所需时间也不同.机器i完成第j个步骤的时间为T[i,j].把半成品从一台机器上搬到另一台机器上也需要一定的时间K.同时,为了保证安全和产品的质量,每台机器最多只能连续完成产品的L个步骤.也就是说,如果有一台机器连续完

【单调队列优化DP】BZOJ1855-[Scoi2010]股票交易

[题目大意] 已知第i天的股票买入价为每股APi,第i天的股票卖出价为每股BPi(数据保证对于每个i,都有APi>=BPi),第i天的一次买入至多只能购买ASi股,一次卖出至多只能卖出BSi股. 股票交易所规定在两次交易(某一天的买入或者卖出均算是一次交易)之间,至少要间隔W天,也就是说如果在第i天发生了交易,那么从第i+1天到第i+W天,均不能发生交易.同时,在任何时间,一个人的手里的股票数不能超过MaxP. 在第1天之前,有一大笔钱(可以认为钱的数目无限),没有任何股票,求T天之后最多赚到多

HDU 4122 Alice&#39;s mooncake shop 单调队列优化dp

Alice's mooncake shop Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=4122 Description The Mid-Autumn Festival, also known as the Moon Festival or Zhongqiu Festival is a popular harvest festival celebrated by Ch

hdu3401 Trade(单调队列优化dp)

Trade Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 4734    Accepted Submission(s): 1587 Problem Description Recently, lxhgww is addicted to stock, he finds some regular patterns after a few d

Tyvj1305最大子序和(单调队列优化dp)

描述 输入一个长度为n的整数序列,从中找出一段不超过M的连续子序列,使得整个序列的和最大. 例如 1,-3,5,1,-2,3 当m=4时,S=5+1-2+3=7当m=2或m=3时,S=5+1=6 输入格式 第一行两个数n,m第二行有n个数,要求在n个数找到最大子序和 输出格式 一个数,数出他们的最大子序和 测试样例1 输入 6 4 1 -3 5 1 -2 3 输出 7 备注 数据范围:100%满足n,m<=300000 是不超过m,不是选m个!!!!! /* 单调队列优化dp 单调队列维护的是前