Assignment 双向队列

http://acm.hdu.edu.cn/webcontest/contest_showproblem.php?pid=1001&ojid=0&cid=12578&hide=0

题意:t测试用例,n个数,给定的值k,求有几个连续的子区间,该区间max-min<k。

思路:双向队列。一个储存区间的最大值,一个储存区间的最小值,设立两个指针i,j,i一直往后走,当最大值-最小值>=k时,这是当前满足条件的最大区间,则其i-1-j+1个子区间都可以,当i走到数组的末尾时,j可能没有走到,这时j到i都可作为子区间。

感想:区间保存最大值,最小值,又在移动的一般都用到队列。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
    int t,n,k,i,j,a[100005];
    deque<int>high;
    deque<int>low;
    ll ans;
    scanf("%d",&t);
    while(t--)
    {
        high.clear();
        low.clear();
        ans=0;
        scanf("%d%d",&n,&k);
        for(i=1;i<=n;i++)
            scanf("%d",&a[i]);
        for(j=i=1;i<=n;i++)//指针
        {
            while(!high.empty()&&high.back()<a[i])
            high.pop_back();
            high.push_back(a[i]);
            while(!low.empty()&&low.back()>a[i])
            low.pop_back();
            low.push_back(a[i]);
            while(!high.empty()&&!low.empty()&&(high.front()-low.front()>=k))//判断
            {
                  ans+=i-j;
                  if(high.front()==a[j])
                    high.pop_front();
                  if(low.front()==a[j])
                    low.pop_front();
                  j++;
                  //cout<<j<<"!"<<endl;
                  //cout<<high.front()<<" "<<low.front()<<endl;
            }
        }
        while(j<=n)//到数组尾部,j没到
        {
            ans+=i-j;
            j++;
        }
        printf("%lld\n",ans);
        ///cout<<ans<<endl;
    }
}

猜你喜欢

转载自blog.csdn.net/qq_37891604/article/details/81070443