首页 > 其他分享 >单调队列优化DP

单调队列优化DP

时间:2024-04-25 23:56:06浏览次数:22  
标签:DP 队列 max 个数 back int 单调 https dp

单调队列优化dp

单调队列可以求某固定区间的最值,所以dp中需要求某固定区间的最值则可以考虑使用单调队列优化

单调队列-滑动窗口

https://www.luogu.com.cn/problem/P1886

/*
 * @Author     : Danc1ng
 * @Date       : 2024-04-24 16:06:34
 * @FilePath   : P1886 滑动窗口 [模板]单调队列
 * @Origin     : https://www.luogu.com.cn/problem/P1886
 * @Description:
 * @Solution   :
 */



#include <bits/stdc++.h>
#define bug cout << "***************" << endl
#define look(x) cout << #x << " -> " << x << endl
#define endl '\n'
#define int long long
#define YES cout << "YES" << endl;
#define NO cout << "NO" << endl;

using namespace std;
typedef pair<int, int> PII;

constexpr int N = 1e6 + 10 , INF = 2e9;

int n,k;
int a[N];

void sliding_window_minimum_deque()
{
    deque<int> q;
    //队列保存数组下标
    //滑动窗口最小值
    for(int i=0;i<n;i++)
    {
        //到当前位置时队列长度>k 弹出队头
        if(q.size()&&i-k+1>q.front()) q.pop_front();

        //保存最小值 所以队列最后的数比新加进来的数还要大 说明之后的答案也不会是他 直接弹出
        while(q.size()&&a[q.back()]>=a[i]) q.pop_back();
        //加入当前数
        q.push_back(i);

        //符合长度为k的窗口下标时 打印答案
        if(i>=k-1) cout<<a[q.front()]<<' ';
    }
    cout<<endl;
}

void sliding_window_maximum_deque()
{
    deque<int> q;
    for(int i=0;i<n;i++)
    {
        if(q.size()&&i-k+1>q.front()) q.pop_front();

        while(q.size()&&a[q.back()]<=a[i]) q.pop_back();

        q.push_back(i);

        if(i>=k-1) cout<<a[q.front()]<<' ';
    }
    cout<<endl;
}

void sliding_window_maximum_normal()
{
    vector<int> q(n);
    //数组模拟单调队列
    int hh=0,tt=-1;

    for(int i=0;i<n;i++)
    {
        if(hh<=tt&&i-k+1>q[hh]) hh++;

        while(hh<=tt&&a[q[tt]]<=a[i]) tt--;
        q[++tt]=i;

        if(i>=k-1) cout<<a[q[hh]]<<' ';
    }
    cout<<endl;

}


void solve()
{
    cin>>n>>k;
    for(int i=0;i<n;i++) cin>>a[i];

    sliding_window_minimum_deque();

    sliding_window_maximum_normal();

}


signed main()
{
    //freopen("check.in","r",stdin);
    //freopen("check.out","r",stdin);
    ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);

    solve();

    return 0;
}

P2034选择数字

https://www.luogu.com.cn/problem/P2034

solution:

f[i][1/0]表示考虑前i个数且第i个数选或不选

f[i][0]=max(f[i-1][0],f[i-1][1]) 第i个不选则看前i-1个选或不选的最大值

考虑f[i][1] 如果第i个数要选 因为最多选连续k个所以第i个数前面能选的数最多连续k-1个
注意到a[i]是非负整数 所以能选就选 则如果i前面的j不被选 则后面j+1到i-1的位置都可以选

i-k,i-k+1,i-k+2,.... i-2,i-1,i
⬆ .... ..... ..... ⬆

f[i][1]=max(f[j][0]+a[i]+a[i-1]+...a[j+1]) 后面a[i]+a[i-1]+....a[j+1]可用前缀和快速求出 所以
f[i][1]=max(f[j][0]+s[i]-s[j])=max(f[j][0]-s[j])+s[i]; (i-k<=j<=i-1)

如果暴力求出max(f[j][0]-s[j])则时间复杂度是O(n^2) 观察到每次j的范围长度都是(i-1)-(i-k)+1=k 是固定的
求固定长度的最值可以用滑动窗口 所以O(1) 即可求出max(f[j][0]-s[j])

/*
origin:https://www.luogu.com.cn/problem/P2034

description:给定一行 n 个非负整数 现在你可以选择其中若干个数,但不能有超过 

标签:DP,队列,max,个数,back,int,单调,https,dp
From: https://www.cnblogs.com/Danc1ng/p/18158962

相关文章

  • dp 集合思想优化
    链接:https://ac.nowcoder.com/acm/contest/78807/D来源:牛客网时间限制:C/C++1秒,其他语言2秒空间限制:C/C++262144K,其他语言524288K64bitIOFormat:%lld题目描述Bingbong有一个长度为n的数字字符串S,该字符串仅包含[0,9]的数字。Bingbong想要从中挑选出若干个字符,......
  • Java ---- 阻塞队列 Blocking Queue
    阻塞队列(BlockingQueue)是一种特殊类型的队列,用于多线程环境中,实现进程通信;常见的Java阻塞队列包括:(1)ArrayBlockingQueue(有界队列)内部是采用数组存储元素的,初始化需要指定容器大小,ArrayBlockingQueue可以用于实现数据缓存、限流、生产者-消费者模式等各种应用。在队列的......
  • 超低功耗三通道低频无线唤醒 ASK 接收芯片DP20RF003
    DP20RF003是一款三通道、超低功耗的ASK接收芯片,可检测30~300KHz范围的LF(低频)载波频率数据并触发唤醒信号,唤醒之后MCU可通过IO实时采集后续接收到的数据,也可以通过SPI或I2C直接从寄存器读取(最多保存8字节数据)。三个独立通道可以配置成不同的唤醒模式,每个通道都具......
  • CIRCLEQ_INSERT_AFTER, C语言循环队列
     CMakeLists.txt#CMakeList.txt:CMakeprojectforllist,includesourceanddefine#projectspecificlogichere.#cmake_minimum_required(VERSION3.2)#Addsourcetothisproject'sexecutable.add_executable(poj2823"main.c""......
  • 线性dp--最长上升子序列变形
    ATwistyMovement洛谷链接:https://www.luogu.com.cn/problem/CF933Acodeforce链接:https://codeforces.com/problemset/problem/933/A题面翻译给定一个序列A,你可以翻转其中的一个区间内的数,求翻转后的序列的最长不下降子序列的长度。(\(|A|\le2000,1\lea_i\le2\))感谢@to......
  • tcp和udp有什么区别-简要
     传输控制协议(TCP)是一种面向连接的、可靠的、基于字节流的传输层通信协议。UDP为应用程序提供了一种无需建立连接就可以发送封装的IP数据包的方法。区别:连接方面,安全方面,传输效率,连接对象数量。1、连接方面区别TCP面向连接(如打电话要先拨号建立连接)。UDP是无连接的,即发送数......
  • 详细介绍tcp和udp有什么区别
    tcp和udp的区别有:1、udp是无连接的,tcp是面向连接的;2、udp是不可靠传输,tcp是可靠传输;3、udp是面向报文传输,tcp是面向字节流传输。  UDPUDP协议全称是用户数据报协议,在网络中它与TCP协议一样用于处理数据包,是一种无连接的协议。在OSI模型中,在第四层——传输层,处于IP协议的......
  • 为什么使用消息队列
    消息队列的基本作用解耦异步削峰引入消息队列会导致什么1.降低系统的可用性:系统引入的外部依赖越多,越容易挂掉2.系统的复杂度变高:使用MQ后可能需要保证消息没有被重复消费、处理消息丢失的情况、保证消息传递的顺序性等等问题3.一致性问题:A系统处理完了直接返回成功......
  • JZ9 用两个栈实现队列
    classSolution{public://用两个栈实现队列栈是先进后出,队列是先进先出//在队列尾部插入整数voidpush(intnode){//入队就正常入栈stack1.push(node);}//在队列头部删除整数,先进先出intpop(){//将第一个栈中......
  • 风险控制 1、如果你的项目发布后失败,主要的原因会是什么? 2、每个团队列出自己项目中
    项目发布失败的主要原因会是:-需求管理不当:项目未能准确捕捉或满足用户需求。资源分配不当:团队可能缺乏必要的技能或资源来完成项目。时间管理问题:项目可能未能在预定时间内完成。沟通不畅:团队成员之间、团队与利益相关者之间的沟通可能存在问题。技术问题:项目可能遇到无法......