51 nod 1275 连续子段的差异(单调队列)

来源:互联网 发布:淘宝有人工客服吗? 编辑:程序博客网 时间:2024/06/05 11:52

1275 连续子段的差异
题目来源: Codility
基准时间限制:1 秒 空间限制:131072 KB 分值: 80 难度:5级算法题
 收藏
 关注
给出一个包括N个元素的整数数组A,包括A本身在内,共有 (N+1)*N / 2个非空子段。例如:1 3 2的子段为{1} {3} {2} {1 3} {3 2} {1 3 2}。在这些子段中,如果最大值同最小值的差异不超过K,则认为这是一个合格的子段。给出数组A和K,求有多少符合条件的子段。例如:3 5 7 6 3,K = 2,符合条件的子段包括:{3} {5} {7} {6} {3} {3 5} {5 7} {7 6} {5 7 6},共9个。
Input
第1行:2个数N, K(1 <= N <= 50000, 0 <= K <= 10^9)第2 - N + 1行:每行1个数,对应数组的元素Ai(0 <= A[i] <= 10^9)
Output
输出符合条件的子段数量。
Input示例
5 235762
Output示例
9


解:第一次用 尺取法加rmq过了 闲杂换 单调队列的写法

用一个队列不好维护 所以用两个维护,一个维护递增序列 一个维护递减序列序列 枚举左结点 延伸右结点

#include<iostream>#include<algorithm>#include<cstdio>#include<cstdlib>#include<cstring>#include<vector>#include<map>#include <bits/stdc++.h>using namespace std;const int N = 300000+10;typedef  long long LL;const LL mod = 998244353;int a[N];int q1[N], q2[N];int main(){    int n, k;    scanf("%d %d",&n, &k);    for(int i=1;i<=n;i++) scanf("%d", &a[i]);    int l1=1,r1=1,l2=1,r2=1;    LL ans=0;    for(int i=1, j=1;i<=n;i++)    {        while(j<=n)        {            while(l1<r1&&a[q1[r1-1]]>=a[j]) r1--;            while(l2<r2&&a[q2[r2-1]]<=a[j]) r2--;            q1[r1++]=j,q2[r2++]=j;            if(a[q2[l2]]-a[q1[l1]]>k) break;            j++;        }        ans+=(j-i);        if(l1<r1&&q1[l1]==i) l1++;        if(l2<r2&&q2[l2]==i) l2++;    }    cout<<ans<<endl;    return 0;}







原创粉丝点击