单调队列

单调队列 && 斜率优化dp 专题

人盡茶涼 提交于 2019-12-19 22:37:28
首先得讲一下单调队列,顾名思义,单调队列就是队列中的每个元素具有单调性,如果是单调递增队列,那么每个元素都是单调递增的,反正,亦然。 那么如何对单调队列进行操作呢? 是这样的:对于单调队列而言,队首和队尾都可以进行出队操作,但只有队尾能够进行入队操作。 至于如何来维护单调队列,这里以单调递增队列为例: 1、如果队列的长度是一定的,首先判断队首元素是否在规定范围内,如果不再,则队首指针向后移动。(至于如何来判断是否在制定范围内,一般而言,我们可以给每个元素设定一个入队的序号,这样就能够知道每个元素原来的顺序了)。 2、每次加入元素是,如果元素小于队尾元素且队列非空,则减小尾指针,队尾元素出队列,直到保持队列单调性为止。 题目链接: http://acm.fzu.edu.cn/problem.php?pid=1894 单调队列的入门题,我们给每个队列中的元素设定一个入队序号,并且设置一个变量来记录当前有多少人离开,这样我们可以维护一个单调递减队列,每次入队的时候,找当前元素适合的位置,每次出队列的时候,判断当前队首元素的入队序号与离开总入数的大小,如果小于等于,则说明当前队首元素应该已经在出队范围内,那么队首指针应该向后移动,直到找到元素的序号比当前离开的总人数大的那个元素,并且出队列。 1 /**********************************************

【HDU】3401:Trade【单调队列优化DP】

喜你入骨 提交于 2019-12-18 13:48:40
Trade Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 5864 Accepted Submission(s): 2022 Problem Description Recently, lxhgww is addicted to stock, he finds some regular patterns after a few days' study. He forecasts the next T days' stock market. On the i'th day, you can buy one stock with the price APi or sell one stock to get BPi. There are some other limits, one can buy at most ASi stocks on the i'th day and at most sell BSi stocks. Two trading days should have a interval of more than W days. That is to say, suppose you traded (any buy

HDU 3401 Trade(单调队列优化)

一曲冷凌霜 提交于 2019-12-18 11:53:27
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3401 题意:炒股。第i天买入一股的价钱api,卖出一股的价钱bpi,最多买入asi股,最多卖出bsi股。两次操作(买入或卖出)中间必须相差W天。炒股时间为n。任意时间手中的股票不大于MaxP。求最大收益。 dp[i][j]代表第i天手上有j股的最大收益,dp[i][j]=max(dp[i-1][j],dp[i-W][k]+(j-k)*ap[i],dp[i-W][k]+(k-j)*bp[i]); dp[i-W][k]+j*ap[i]-k*ap[i]; dp[i-W][k]+k*bp[i]-j*bp[i]; 用单调队列维护 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 #include<string> 6 #include<algorithm> 7 #define inf 0x7fffffff 8 struct op{ 9 int x,p; 10 }q[20005],temp; 11 int n,m,w; 12 int ap[2005],bp[2005],as[2005],bs[2005]; 13 int dp[2005][2005],h,t; 14 int main(){

单调队列和单调栈

▼魔方 西西 提交于 2019-12-18 01:51:46
  最近学到了dp,一开始以为思维的体操是时候绽放了....   傲娇.jpg   ....但是....   下面回归正题: 单调队列 :单调队列分为两种,即单调递增和单调递减队列,简单的理解就是基本队列赋予严格的递增或递减的单调性即可。   单调队列一般用于优化,一般有如下用途。   下面给一道单调队列的模版题:   题目链接 :   题意:意思就是给出一个区间长度k和n个元素的数组a, 从a的第一个k大小的连续区间开始直到最后一个连续区间,找到每次区间里的最大值和最小值,具体输出形式见题面。   本题思路:刚好满足单调队列的性质,每次维护区间内的最值并保存就ok。   参考代码: 1 #include <iostream> 2 #include <deque> 3 #include <cstdio> 4 using namespace std; 5 6 typedef pair<int ,int > P; 7 const int maxn = 1e6 + 5; 8 int a[maxn], n, k, Max[maxn], Min[maxn], nummax = 0, nummin = 0; 9 10 void getMax() { 11 deque <P> p; 12 P now; 13 p.push_front(make_pair(a[0], 0)); 14 if(k ==

单调队列

我与影子孤独终老i 提交于 2019-12-17 15:55:44
单调队列,顾名思义就是具有单调性的队列O(∩_∩)O~,一般的队列只能从队尾入队、队首出队;为了保持单调队列的单调性,单调队列除具有这两种性质外,还可以从队尾出队。 以单增的单调队列为例,当元素t要入队时,先要从队尾依次弹出所有>=t的元素,再将t加在队尾。 举个例子,如果序列:1 3 -1 -3 10要构成单调队列, 先将元素“1”放入队列中,以初始化队列, 接着元素“3”要入队,队尾元素“1”比“3”小,因此“3”可以直接入队,队列变为1 3, 接着“-1”要入队,从队尾依次弹出元素“3”“1”后将“-1”入队,队列变为-1, 同理“-3”入队后,队列变为-3, “10”入队后,队列变为-3 10 单调队列有什么用呢?看一道例题:(poj2823) 给定含有n个元素的无序序列a[],和一个整数k,要求求出a[]中每连续k个元素组成的序列中的最小值(或最大值),这样的值可能有1个或n-k+1个。 比较简单的方式,是每次都将k个数的最值找出,具有O(K*n)的时间复杂度。但如果用单调队列的话,我们可以在O(n)的时间内求解,原因是每个元素最多入队一次、出队一次。 要解决该题,我们还要记录每个元素在原序列中的位置p,每次只需从队首开始找到跟当前元素a[i]距离不大于k的元素(即是i-p+1<=k)输出即可。 一、 什么是单调(双端)队列 单调队列,顾名思义,就是一个元素单调的队列

hdu3401 Trade(单调队列优化dp)

天涯浪子 提交于 2019-12-17 00:44:09
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 days' study. He forecasts the next T days' stock market. On the i'th day, you can buy one stock with the price APi or sell one stock to get BPi. There are some other limits, one can buy at most ASi stocks on the i'th day and at most sell BSi stocks. Two trading days should have a interval of more than W days. That is to say, suppose you traded (any buy

HDU 3401 Trade dp+单调队列优化

南笙酒味 提交于 2019-12-17 00:43:51
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3401 Trade Time Limit: 2000/1000 MS (Java/Others)Memory Limit: 32768/32768 K (Java/Others) 问题描述 Recently, lxhgww is addicted to stock, he finds some regular patterns after a few days' study. He forecasts the next T days' stock market. On the i'th day, you can buy one stock with the price APi or sell one stock to get BPi. There are some other limits, one can buy at most ASi stocks on the i'th day and at most sell BSi stocks. Two trading days should have a interval of more than W days. That is to say, suppose you traded (any buy or sell stocks is

单调序列例题

[亡魂溺海] 提交于 2019-12-16 14:11:58
一, 给定一个区间,求所有区间长度为L的区间的最大值和最小值 二, 该题有很多做法。 自然用的是滑动窗口(单调队列) 可能的做法: O(nlogn) 的线段树 O(nlogn) 的带删除优先队列(对顶堆) 还能再快一点吗? O(n)-O(1)RMQ 代替线段树 三, 单调队列和单调栈的意思一样,始终要你维持一个单调递增或者递减的属性。 比你小还比你强,我哭了。 1 const int N= 5000010 ; 2 int q[N],l=1,r=1,a[N] , mx , mn, inq[N],n,m; inline void ins(int x){ 3 while(l<r&&q [r-1]<=a[x])r--; 4 q[r]=a[x]; inq[r]=x;r++; 5 } 6 inline int getmax(int cur){ 7 for(l<r;l++)if(cur- inq[l] <m)return q[l] ;} 这个图片我希望能复制进去~ 肯定不行啊。。 单调队列 四, 老老实实看来下代码,似乎是改了下 push(),以及把first改成了getmax() 但是如果已经单调了,挺没有必要的。 来源: https://www.cnblogs.com/beiyueya/p/12040429.html

DP单调队列--斜率优化P3195

霸气de小男生 提交于 2019-12-08 11:13:30
题意: https://www.luogu.com.cn/problem/P3195 思路: https://www.luogu.com.cn/problemnew/solution/P3195 1 #define IOS ios_base::sync_with_stdio(0); cin.tie(0); 2 #include <cstdio>//sprintf islower isupper 3 #include <cstdlib>//malloc exit strcat itoa system("cls") 4 #include <iostream>//pair 5 #include <fstream>//freopen("C:\\Users\\13606\\Desktop\\Input.txt","r",stdin); 6 #include <bitset> 7 //#include <map> 8 //#include<unordered_map> 9 #include <vector> 10 #include <stack> 11 #include <set> 12 #include <string.h>//strstr substr strcat 13 #include <string> 14 #include <time.h>// srand(((unsigned

烽火传递【单调队列优化dp】

核能气质少年 提交于 2019-12-05 14:49:29
题目大意: 1.给出长度为n的数组,要求每m个连续的元素之间必须选一个值作为代价,求该数组的最小代价。 题解思路: 1.显然是线性dp,dp【i】表示选择第 i 个元素时的最小总代价。很明显状态转移方程为 dp[i] = min(dp[j]) + a[i]。(i - m <= j <= i - 1)。 但是在求min(dp[j])的时候,我们需要遍历一遍长度为m大小的区间,m极限与n同大。时间负责度0(N^2)。显然会超时。 2.我们需要用 单调队列来维护长度为m大小区间内的最小值,队头即为最小值,直接O(1)得到min(dp[j]), 就可以避免超时。 代码如下: 1 #include<stdio.h> 2 #include<deque> 3 #include<algorithm> 4 const int MAXN = 2e5 + 100; 5 using namespace std; 6 const int inf = 0x3f3f3f3f; 7 8 int n, m, a[MAXN]; 9 int dp[MAXN]; //表示第 i 个烽火台放置烽火时的最小总代价 10 deque<int> Q; 11 12 int main() 13 { 14 scanf("%d%d",&n, &m); 15 for(int i = 1; i <= n; i ++) 16 scanf("