[多校2015.01.1002 单调队列] hdu 5289 Assignment

来源:互联网 发布:人机交互与人工智能 编辑:程序博客网 时间:2024/06/05 15:55

题意:

给你n个人和一个k

问你把这n个人分成多少个连续的子区间,要求区间每个数两两相差绝对值小于k

思路:

我们仅仅只需要对于当前位置,最左边那个和它绝对值相差大于等于k 的位置在哪

假设对于i这个位置,最左边的位置是tep,不存在的话tep=0

那么当且位置的贡献就是 sum[i]=min(i-max(x1,x2),sum[i-1]+1);

那么对于这个位置怎么求的话,我是使用了两个单调队列

同时维护两个单调队列

一个最大一个最小。

代码:

#include"cstdlib"#include"cstdio"#include"cstring"#include"cmath"#include"queue"#include"algorithm"#include"iostream"#include"map"using namespace std;#define N 222222#define ll __int64int q1[N],q2[N],v[N];int main(){    int t;    cin>>t;    while(t--)    {        int n,k;        scanf("%d%d",&n,&k);        for(int i=1; i<=n; i++) scanf("%d",&v[i]);        int top1,top2,ed1,ed2,x1,x2;        top1=top2=ed1=ed2=x1=x2=0;        ll ans=0,sum=0;        for(int i=1; i<=n; i++)        {            while(top1<ed1 && v[q1[ed1-1]]<=v[i] ) ed1--;  //Max            q1[ed1++]=i;            while(top2<ed2 && v[q2[ed2-1]]>=v[i] ) ed2--;  //Min            q2[ed2++]=i;            while(v[q1[top1]]-v[q2[top2]]>=k)            {                if(q1[top1]<q2[top2]) x1=q1[top1++];                else x2=q2[top2++];            }            sum=min(sum+1,(ll)i-max(x1,x2));            ans+=sum;        }        printf("%I64d\n",ans);    }    return 0;}


0 0
原创粉丝点击