您的位置:首页 > 其它

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

2015-07-26 14:45 363 查看
题意:

给你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 __int64
int q1
,q2
,v
;
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: