双端队列 HDOJ 3530 Subsequence

题目传送门

题意:问最长子序列,满足区间最大值 - 最小值在[m, k]之间

分析:用双端队列维护最大值和最小值,保存的是位置。当满足条件时,更新最大值。

/************************************************
* Author        :Running_Time
* Created Time  :2015/9/25 星期五 08:50:32
* File Name     :A_deque.cpp
 ************************************************/

#include <cstdio>
#include <algorithm>
#include <iostream>
#include <sstream>
#include <cstring>
#include <cmath>
#include <string>
#include <vector>
#include <queue>
#include <deque>
#include <stack>
#include <list>
#include <map>
#include <set>
#include <bitset>
#include <cstdlib>
#include <ctime>
using namespace std;

#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
typedef long long ll;
const int N = 1e5 + 10;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
const double EPS = 1e-8;
int a[N];

int main(void)    {
    int n, m, k;
    while (scanf ("%d%d%d", &n, &m, &k) == 3)   {
        deque<int> Q1, Q2;
        int ans = 0, l = 1;
        for (int i=1; i<=n; ++i) {
            scanf ("%d", &a[i]);
            while (!Q1.empty () && a[Q1.back ()] <= a[i])    Q1.pop_back ();
            Q1.push_back (i);
            while (!Q2.empty () && a[Q2.back ()] >= a[i])    Q2.pop_back ();
            Q2.push_back (i);
            while (!Q1.empty () && !Q2.empty () && a[Q1.front ()] - a[Q2.front ()] > k)   {
                if (Q1.front () < Q2.front ())  {
                    l = Q1.front () + 1;    Q1.pop_front ();
                }
                else    {
                    l = Q2.front () + 1;    Q2.pop_front ();
                }
            }
            if (!Q1.empty () && !Q2.empty () && a[Q1.front ()] - a[Q2.front ()] >= m)   {
                if (ans < i - l + 1)    ans = i - l + 1;
            }
        }
        printf ("%d\n", ans);
    }

    return 0;
}

数组模拟:

/************************************************
* Author        :Running_Time
* Created Time  :2015/9/22 星期二 15:49:25
* File Name     :A.cpp
 ************************************************/

#include <cstdio>
#include <algorithm>
#include <iostream>
#include <sstream>
#include <cstring>
#include <cmath>
#include <string>
#include <vector>
#include <queue>
#include <deque>
#include <stack>
#include <list>
#include <map>
#include <set>
#include <bitset>
#include <cstdlib>
#include <ctime>
using namespace std;

#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
typedef long long ll;
const int N = 1e5 + 10;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
const double EPS = 1e-8;
int dq1[N], dq2[N], a[N];

int main(void)    {
    int n, m, k;
    while (scanf ("%d%d%d", &n, &m, &k) == 3)   {
        for (int i=1; i<=n; ++i)    {
            scanf ("%d", &a[i]);
        }
        int f1 = 0, f2 = 0, b1 = 0, b2 = 0, l = 1;
        int ans = 0;
        for (int i=1; i<=n; ++i)    {
            while (f1 < b1 && a[dq1[b1-1]] <= a[i])  b1--;
            dq1[b1++] = i;
            while (f2 < b2 && a[dq2[b2-1]] >= a[i])  b2--;
            dq2[b2++] = i;
            while (f1 < b1 && f2 < b2 && a[dq1[f1]] - a[dq2[f2]] > k) {
                if (dq1[f1] < dq2[f2])  {
                    l = dq1[f1++] + 1;
                }
                else    l = dq2[f2++] + 1;
            }
            if (f1 < b1 && f2 < b2 && a[dq1[f1]] - a[dq2[f2]] >= m)   {
                ans = max (ans, i - l + 1);
            }
        }
        printf ("%d\n", ans);
    }

    return 0;
}

  

时间: 2025-01-02 04:18:41

双端队列 HDOJ 3530 Subsequence的相关文章

单调队列(双端队列) poj2823 hdoj3415 hdoj3530

单调队列及其应用(双端队列) 单调队列,望文生义,就是指队列中的元素是单调的.如:{a1,a2,a3,a4--an}满足a1<=a2<=a3--<=an,a序列便是单调递增序列.同理递减队列也是存在的. 单调队列的出现可以简化问题,队首元素便是最大(小)值,这样,选取最大(小)值的复杂度便为o(1),由于队列的性质,每个元素入队一次,出队一次,维护队列的复杂度均摊下来便是o(1). 如何维护单调队列呢,以单调递增序列为例: 1.如果队列的长度一定,先判断队首元素是否在规定范围内,如果超范

8、泛型程序设计与c++标准模板库2.3双端队列容器

双端队列容器是一种放松了访问权限的队列.除了从队列的首部和尾部访问元素外,标准的双端队列也支持通过使用下标操作符"[]"进行直接访问. 它提供了直接访问和顺序访问方法.其头文件为<deque>. 1)双端队列容器的构造函数 有4中形式的构造函数: deque();//构造size()为0的双端队列容器 deque(size_type n,const T& v=T());//初始化大小为n的双端队列,第二个参数是每个元素的初始值,默认为T()构造的对象 deque(c

习题3.26双端队列

#include<stdio.h> #include<stdlib.h> struct Node; struct Queue; typedef struct Node * PtrToNode; typedef struct Queue * PtrToQ; struct Node{ PtrToNode Pre; PtrToNode Next; ElemenType Ele; } struct Queue{ PtrToNode front; PtrToNode rear; }; Ptr

nyoj1117 鸡蛋队列 (双端队列,deque)

题目1117 题目信息 运行结果 本题排行 讨论区 鸡蛋队列 时间限制:1000 ms  |  内存限制:65535 KB 难度:1 描述 将两根筷子平行的放在一起,就构成了一个队列.将带有编号的鸡蛋放到两根筷子之间叫做入队(push),将筷子之间的鸡蛋拿出来叫做出队(pop).但这两种方式有特殊的定义,对于入队,只能将鸡蛋从队列的尾部向里放入:对于出队,只能将鸡蛋从队列的头部向外将鸡蛋拿出来. 将①.②入队: 头____________尾                         ___

算法导论之八(10.1-5单数组实现双端队列)

算法导论第三版P131 题目: 10.1-5 栈插入和删除元素只能在同一端进行,队列的插入操作和删除操作分别在两端进行,与它们不同的,有一种双端队列(deque),其插入和删除操作都可以在两端进行.写出4个时间均为O(1)的过程,分别实现在双端队列插入和删除元素的操作,该队列使用一个数组实现的. 注意点: 1.左右端点指向的位置是类似于队列中的tail端点,是下一个插入操作的位置. 2.然后注意遍历的时候,左端点和右端点的位置关系,有两种可能,所以遍历的方式不一样. 代码: /* * 使用单数组

HDU 4286 Data Handler (双端队列)

Data Handler Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2455    Accepted Submission(s): 616 Problem Description You are in charge of data in a company, so you are called "Data Handler&qu

队列的应用:双端队列

双端队列(Deque:double ended queue)就是一个两端都是结尾的队列.队列的每一端都可以插入数据项和移除数据项.相对于普通队列,双端队列的入队和出队操作在两端都可进行. 双端队列的示意图: left:左端    right:右端 这里我们使用最常用的顺序结构来存储双端队列,为了节省空间,把它首尾相连,构成循环队列.并且规定left指向左端的第一个元素,right指向右端的下一个位置.那么队空的判断则是left==right,队满是(left-1+MAX)%MAX==right或

hdu-5929 Basic Data Structure(双端队列+模拟)

题目链接: Basic Data Structure Time Limit: 7000/3500 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 207    Accepted Submission(s): 41 Problem Description Mr. Frog learned a basic data structure recently, which is called

Vijos1834 NOI2005 瑰丽华尔兹 动态规划 单调双端队列优化

设dp[t][x][y]表示处理完前t个时间段,钢琴停留在(x,y)处,最多可以走多少个格子 转移时只需逆着当前倾斜的方向统计len个格子(len为时间区间的长度,len=t-s+1),如果遇到障碍就中断 转移过程可以用单调非递增的双端队列优化 1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 5 const int maxN=202; 6 const int inf=0x3f3f3f3f