惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

V2EX - 技术
V2EX - 技术
阮一峰的网络日志
阮一峰的网络日志
博客园 - 叶小钗
月光博客
月光博客
人人都是产品经理
人人都是产品经理
美团技术团队
J
Java Code Geeks
博客园 - 聂微东
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
罗磊的独立博客
博客园 - 【当耐特】
GbyAI
GbyAI
P
Proofpoint News Feed
T
The Exploit Database - CXSecurity.com
D
Docker
Vercel News
Vercel News
小众软件
小众软件
NISL@THU
NISL@THU
Simon Willison's Weblog
Simon Willison's Weblog
雷峰网
雷峰网
Spread Privacy
Spread Privacy
T
Threatpost
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
P
Palo Alto Networks Blog
爱范儿
爱范儿
L
LINUX DO - 热门话题
博客园_首页
I
Intezer
博客园 - Franky
Security Latest
Security Latest
Scott Helme
Scott Helme
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
S
Schneier on Security
O
OpenAI News
WordPress大学
WordPress大学
TaoSecurity Blog
TaoSecurity Blog
Security Archives - TechRepublic
Security Archives - TechRepublic
G
Google Developers Blog
M
MIT News - Artificial intelligence
The Register - Security
The Register - Security
Cisco Talos Blog
Cisco Talos Blog
Forbes - Security
Forbes - Security
C
Cybersecurity and Infrastructure Security Agency CISA
T
Tenable Blog
SecWiki News
SecWiki News
酷 壳 – CoolShell
酷 壳 – CoolShell
C
Cyber Attacks, Cyber Crime and Cyber Security
N
News | PayPal Newsroom
量子位
博客园 - 三生石上(FineUI控件)

gyro永不抽风!

深入理解 Zyzzyva 协议 - gyro永不抽风! 深入理解 PBFT 协议 - gyro永不抽风! 西瓜书 绪论 习题 - gyro永不抽风! PyTorch Data Augmentation 数据增广 - gyro永不抽风! 读论文——YOLO v1 - gyro永不抽风! P1363 幻象迷宫 - DFS - gyro永不抽风! POJ 2823 滑动窗口 单调队列 - 致逝去的青春 leetcode 1787 使所有区间的异或结果为零 - DP - 随机跳题计划 P2210 Haywire - 状压 DP VSCode绕开腾讯云COS防盗链 | Markdown魔改过程 - gyro永不抽风! GAN(对抗生成网络)的基本原理以及数学证明 - gyro永不抽风! Canny边缘检测算法(基于OpenCV的Java实现) - gyro永不抽风!
P3572 [POI2014] PTA-Little Bird - DP 单调队列
博主: gyro永不抽风 · 2022-04-08 · via gyro永不抽风!
  • 发布时间:
  • 2290次浏览
  • 暂无评论
  • 694字数
  • 分类: 技术
  1. 首页
  2. 正文  
  3. 分享到:

题面

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

题解

首先,不难列出方程:$f[i]$ 代表跳到 $i$ 的最小疲劳值

$$
f[i] = \min_{i - k \leq j < i} \{f[j] + (a[i] \geq a[j])\}
$$

时间复杂度为 $O(qn^2)$,不理想。但是不难发现,这道题可以用单调队列进行优化。为什么?

如下状态一定是更优的:随着 index 递增

  • $f$ 不下降(第一维比较)
  • $f$ 若相同,同时有 $a$ 不上升(第二维比较)

所以我们就可以用单调队列来维护 index,时间复杂度为 $O(qn)$

注意:

  • 初值的设定,详见代码
  • 写的顺序和单调队列的模板稍微有一点不同,因为 $i - k \leq j < i$,右边的小于号不是小于等于号,即 $f[i]$ 不能被自己更新,所以调整了一下逻辑块的顺序。

代码

#include <iostream>

using namespace std;

const int maxn = 1e6+5;

int qq, n, k, head, tail, a[maxn], f[maxn], q[maxn];

int main() {
    cin >> n;
    for (int i = 1; i <= n; i ++) cin >> a[i];
    cin >> qq;
    while (qq --> 0) {
        cin >> k;
        head = 1; tail = 1; q[1] = 1;
        for (int i = 2; i <= n; i ++) {
            while (head <= tail && q[head] < i - k) head ++;
            f[i] = f[q[head]] + (a[i] >= a[q[head]]);
            while (head <= tail && (
                f[i] < f[q[tail]] || (
                    f[i] == f[q[tail]] && a[i] >= a[q[tail]]
                )
            )) tail --;
            q[++ tail] = i;
        }
        cout << f[n] << endl;
    }
    return 0;
}

赞赏作者

13

P3572 [POI2014] PTA-Little Bird - DP 单调队列

题面

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

题解

首先,不难列出方程:$f[i]$ 代表跳到 $i$ 的最小疲劳值

$$
f[i] = \min_{i - k \leq j < i} \{f[j] + (a[i] \geq a[j])\}
$$

时间复杂度为 $O(qn^2)$,不理想。但是不难发现,这道题可以用单调队列进行优化。为什么?

如下状态一定是更优的:随着 index 递增

  • $f$ 不下降(第一维比较)
  • $f$ 若相同,同时有 $a$ 不上升(第二维比较)

所以我们就可以用单调队列来维护 index,时间复杂度为 $O(qn)$

注意:

  • 初值的设定,详见代码
  • 写的顺序和单调队列的模板稍微有一点不同,因为 $i - k \leq j < i$,右边的小于号不是小于等于号,即 $f[i]$ 不能被自己更新,所以调整了一下逻辑块的顺序。

代码

#include <iostream>

using namespace std;

const int maxn = 1e6+5;

int qq, n, k, head, tail, a[maxn], f[maxn], q[maxn];

int main() {
    cin >> n;
    for (int i = 1; i <= n; i ++) cin >> a[i];
    cin >> qq;
    while (qq --> 0) {
        cin >> k;
        head = 1; tail = 1; q[1] = 1;
        for (int i = 2; i <= n; i ++) {
            while (head <= tail && q[head] < i - k) head ++;
            f[i] = f[q[head]] + (a[i] >= a[q[head]]);
            while (head <= tail && (
                f[i] < f[q[tail]] || (
                    f[i] == f[q[tail]] && a[i] >= a[q[tail]]
                )
            )) tail --;
            q[++ tail] = i;
        }
        cout << f[n] << endl;
    }
    return 0;
}