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

推荐订阅源

Engineering at Meta
Engineering at Meta
博客园_首页
H
Help Net Security
WordPress大学
WordPress大学
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
罗磊的独立博客
博客园 - 三生石上(FineUI控件)
B
Blog
I
InfoQ
SecWiki News
SecWiki News
T
Tailwind CSS Blog
Spread Privacy
Spread Privacy
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
V
Vulnerabilities – Threatpost
N
Netflix TechBlog - Medium
P
Palo Alto Networks Blog
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Vercel News
Vercel News
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
K
Kaspersky official blog
M
MIT News - Artificial intelligence
S
Schneier on Security
T
Threat Research - Cisco Blogs
F
Fortinet All Blogs
Cyberwarzone
Cyberwarzone
Scott Helme
Scott Helme
aimingoo的专栏
aimingoo的专栏
Martin Fowler
Martin Fowler
MyScale Blog
MyScale Blog
The Cloudflare Blog
Recent Announcements
Recent Announcements
Security Latest
Security Latest
G
GRAHAM CLULEY
IT之家
IT之家
Y
Y Combinator Blog
The Last Watchdog
The Last Watchdog
腾讯CDC
Google DeepMind News
Google DeepMind News
V
V2EX
S
Securelist
TaoSecurity Blog
TaoSecurity Blog
B
Blog RSS Feed
S
SegmentFault 最新的问题
博客园 - 叶小钗
P
Proofpoint News Feed
云风的 BLOG
云风的 BLOG
Project Zero
Project Zero
G
Google Developers Blog
Google DeepMind News
Google DeepMind News
F
Full Disclosure

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;
}